Merge from HEAD the SMB signing patch that I developed a couple of weeks
[Samba/gebeck_regimport.git] / source / libsmb / smb_signing.c
blobc71543959dc296e2bc76c3f59baff2e36c0b28d6
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 void store_sequence_for_reply(struct outstanding_packet_lookup **list,
46 uint16 mid, uint32 reply_seq_num)
48 struct outstanding_packet_lookup *t;
50 t = smb_xmalloc(sizeof(*t));
51 ZERO_STRUCTP(t);
53 t->mid = mid;
54 t->reply_seq_num = reply_seq_num;
57 * Add to the *start* of the list not the end of the list.
58 * This ensures that the *last* send sequence with this mid
59 * is returned by preference.
60 * This can happen if the mid wraps and one of the early
61 * mid numbers didn't get a reply and is still lurking on
62 * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>.
65 DLIST_ADD(*list, t);
66 DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
67 (unsigned int)reply_seq_num, (unsigned int)mid ));
70 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
71 uint16 mid, uint32 *reply_seq_num)
73 struct outstanding_packet_lookup *t;
75 for (t = *list; t; t = t->next) {
76 if (t->mid == mid) {
77 *reply_seq_num = t->reply_seq_num;
78 DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
79 (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
80 DLIST_REMOVE(*list, t);
81 SAFE_FREE(t);
82 return True;
85 return False;
88 /***********************************************************
89 SMB signing - Common code before we set a new signing implementation
90 ************************************************************/
92 static BOOL cli_set_smb_signing_common(struct cli_state *cli)
94 if (!cli->sign_info.negotiated_smb_signing
95 && !cli->sign_info.mandatory_signing) {
96 return False;
99 if (cli->sign_info.doing_signing) {
100 return False;
103 if (cli->sign_info.free_signing_context)
104 cli->sign_info.free_signing_context(&cli->sign_info);
106 /* These calls are INCOMPATIBLE with SMB signing */
107 cli->readbraw_supported = False;
108 cli->writebraw_supported = False;
110 return True;
113 /***********************************************************
114 SMB signing - Common code for 'real' implementations
115 ************************************************************/
117 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
119 if (si->mandatory_signing) {
120 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
123 si->doing_signing = True;
124 DEBUG(5, ("SMB signing enabled!\n"));
126 return True;
129 static void mark_packet_signed(char *outbuf)
131 uint16 flags2;
132 flags2 = SVAL(outbuf,smb_flg2);
133 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
134 SSVAL(outbuf,smb_flg2, flags2);
137 /***********************************************************
138 SMB signing - NULL implementation - calculate a MAC to send.
139 ************************************************************/
141 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
143 /* we can't zero out the sig, as we might be trying to send a
144 session request - which is NBT-level, not SMB level and doesn't
145 have the field */
146 return;
149 /***********************************************************
150 SMB signing - NULL implementation - check a MAC sent by server.
151 ************************************************************/
153 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
155 return True;
158 /***********************************************************
159 SMB signing - NULL implementation - free signing context
160 ************************************************************/
162 static void null_free_signing_context(struct smb_sign_info *si)
164 return;
168 SMB signing - NULL implementation - setup the MAC key.
170 @note Used as an initialisation only - it will not correctly
171 shut down a real signing mechanism
174 static BOOL null_set_signing(struct smb_sign_info *si)
176 si->signing_context = NULL;
178 si->sign_outgoing_message = null_sign_outgoing_message;
179 si->check_incoming_message = null_check_incoming_message;
180 si->free_signing_context = null_free_signing_context;
182 return True;
186 * Free the signing context
189 static void free_signing_context(struct smb_sign_info *si)
191 if (si->free_signing_context) {
192 si->free_signing_context(si);
193 si->signing_context = NULL;
196 null_set_signing(si);
200 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok)
202 if (good) {
204 if (!si->doing_signing) {
205 si->doing_signing = True;
208 if (!si->seen_valid) {
209 si->seen_valid = True;
212 } else {
213 if (!si->mandatory_signing && !si->seen_valid) {
215 if (!must_be_ok) {
216 return True;
218 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
219 DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and client \
220 isn't sending correct signatures. Turning off.\n"));
221 si->negotiated_smb_signing = False;
222 si->allow_smb_signing = False;
223 si->doing_signing = False;
224 free_signing_context(si);
225 return True;
226 } else if (!must_be_ok) {
227 /* This packet is known to be unsigned */
228 return True;
229 } else {
230 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
231 if (seq)
232 DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
233 return False;
236 return True;
239 /***********************************************************
240 SMB signing - Simple implementation - calculate a MAC on the packet
241 ************************************************************/
243 static void simple_packet_signature(struct smb_basic_signing_context *data,
244 const uchar *buf, uint32 seq_number,
245 unsigned char calc_md5_mac[16])
247 const size_t offset_end_of_sig = (smb_ss_field + 8);
248 unsigned char sequence_buf[8];
249 struct MD5Context md5_ctx;
252 * Firstly put the sequence number into the first 4 bytes.
253 * and zero out the next 4 bytes.
255 * We do this here, to avoid modifying the packet.
258 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
260 SIVAL(sequence_buf, 0, seq_number);
261 SIVAL(sequence_buf, 4, 0);
263 /* Calculate the 16 byte MAC - but don't alter the data in the
264 incoming packet.
266 This makes for a bit of fussing about, but it's not too bad.
268 MD5Init(&md5_ctx);
270 /* intialise with the key */
271 MD5Update(&md5_ctx, data->mac_key.data,
272 data->mac_key.length);
274 /* copy in the first bit of the SMB header */
275 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
277 /* copy in the sequence number, instead of the signature */
278 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
280 /* copy in the rest of the packet in, skipping the signature */
281 MD5Update(&md5_ctx, buf + offset_end_of_sig,
282 smb_len(buf) - (offset_end_of_sig - 4));
284 /* calculate the MD5 sig */
285 MD5Final(calc_md5_mac, &md5_ctx);
289 /***********************************************************
290 SMB signing - Client implementation - send the MAC.
291 ************************************************************/
293 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
295 unsigned char calc_md5_mac[16];
296 struct smb_basic_signing_context *data = si->signing_context;
297 uint32 send_seq_num;
299 if (!si->doing_signing)
300 return;
302 /* JRA Paranioa test - we should be able to get rid of this... */
303 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
304 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
305 smb_len(outbuf) ));
306 abort();
309 /* mark the packet as signed - BEFORE we sign it...*/
310 mark_packet_signed(outbuf);
312 if (data->trans_info)
313 send_seq_num = data->trans_info->send_seq_num;
314 else
315 send_seq_num = data->send_seq_num;
317 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
319 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
320 dump_data(10, (const char *)calc_md5_mac, 8);
322 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
324 /* cli->outbuf[smb_ss_field+2]=0;
325 Uncomment this to test if the remote server actually verifies signatures...*/
327 if (data->trans_info)
328 return;
330 data->send_seq_num++;
331 store_sequence_for_reply(&data->outstanding_packet_list,
332 SVAL(outbuf,smb_mid), data->send_seq_num);
333 data->send_seq_num++;
336 /***********************************************************
337 SMB signing - Client implementation - check a MAC sent by server.
338 ************************************************************/
340 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
342 BOOL good;
343 uint32 reply_seq_number;
344 uint32 saved_seq;
345 unsigned char calc_md5_mac[16];
346 unsigned char *server_sent_mac;
348 struct smb_basic_signing_context *data = si->signing_context;
350 if (!si->doing_signing)
351 return True;
353 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
354 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
355 return False;
358 if (data->trans_info) {
359 reply_seq_number = data->trans_info->reply_seq_num;
360 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
361 SVAL(inbuf, smb_mid), &reply_seq_number)) {
362 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
363 (unsigned int) SVAL(inbuf, smb_mid) ));
364 return False;
367 saved_seq = reply_seq_number;
368 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
370 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
371 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
373 if (!good) {
374 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
375 dump_data(5, (const char *)calc_md5_mac, 8);
377 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
378 dump_data(5, (const char *)server_sent_mac, 8);
379 #if 1 /* JRATEST */
381 int i;
382 reply_seq_number -= 5;
383 for (i = 0; i < 10; i++, reply_seq_number++) {
384 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
385 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
386 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
387 We were expecting seq %u\n", reply_seq_number, saved_seq ));
388 break;
392 #endif /* JRATEST */
394 } else {
395 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
396 dump_data(10, (const char *)server_sent_mac, 8);
398 return signing_good(inbuf, si, good, saved_seq, must_be_ok);
401 /***********************************************************
402 SMB signing - Simple implementation - free signing context
403 ************************************************************/
405 static void simple_free_signing_context(struct smb_sign_info *si)
407 struct smb_basic_signing_context *data = si->signing_context;
408 struct outstanding_packet_lookup *list = data->outstanding_packet_list;
410 while (list) {
411 struct outstanding_packet_lookup *old_head = list;
412 DLIST_REMOVE(list, list);
413 SAFE_FREE(old_head);
416 data_blob_free(&data->mac_key);
418 if (data->trans_info)
419 SAFE_FREE(data->trans_info);
421 SAFE_FREE(si->signing_context);
423 return;
426 /***********************************************************
427 SMB signing - Simple implementation - setup the MAC key.
428 ************************************************************/
430 BOOL cli_simple_set_signing(struct cli_state *cli,
431 const DATA_BLOB user_session_key,
432 const DATA_BLOB response)
434 struct smb_basic_signing_context *data;
436 if (!user_session_key.length)
437 return False;
439 if (!cli_set_smb_signing_common(cli)) {
440 return False;
443 if (!set_smb_signing_real_common(&cli->sign_info)) {
444 return False;
447 data = smb_xmalloc(sizeof(*data));
448 memset(data, '\0', sizeof(*data));
450 cli->sign_info.signing_context = data;
452 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
454 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
456 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
457 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
459 if (response.length) {
460 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
461 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
462 dump_data(10, (const char *)response.data, response.length);
463 } else {
464 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
467 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
469 /* Initialise the sequence number */
470 data->send_seq_num = 0;
472 /* Initialise the list of outstanding packets */
473 data->outstanding_packet_list = NULL;
475 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
476 cli->sign_info.check_incoming_message = client_check_incoming_message;
477 cli->sign_info.free_signing_context = simple_free_signing_context;
479 return True;
482 /***********************************************************
483 Tell client code we are in a multiple trans reply state.
484 We call this after the last outgoing trans2 packet (which
485 has incremented the sequence numbers), so we must save the
486 current mid and sequence number -2.
487 ************************************************************/
489 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
491 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
493 if (!cli->sign_info.doing_signing || !data)
494 return;
496 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
497 ZERO_STRUCTP(data->trans_info);
499 data->trans_info->send_seq_num = data->send_seq_num-2;
500 data->trans_info->mid = mid;
501 data->trans_info->reply_seq_num = data->send_seq_num-1;
503 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
504 data->send_seq_num = %u\n",
505 (unsigned int)data->trans_info->mid,
506 (unsigned int)data->trans_info->reply_seq_num,
507 (unsigned int)data->trans_info->send_seq_num,
508 (unsigned int)data->send_seq_num ));
511 /***********************************************************
512 Tell client code we are out of a multiple trans reply state.
513 ************************************************************/
515 void cli_signing_trans_stop(struct cli_state *cli)
517 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
519 if (!cli->sign_info.doing_signing || !data)
520 return;
522 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
523 data->send_seq_num = %u\n",
524 (unsigned int)data->trans_info->mid,
525 (unsigned int)data->trans_info->reply_seq_num,
526 (unsigned int)data->trans_info->send_seq_num,
527 (unsigned int)data->send_seq_num ));
529 SAFE_FREE(data->trans_info);
530 data->trans_info = NULL;
533 /***********************************************************
534 SMB signing - TEMP implementation - calculate a MAC to send.
535 ************************************************************/
537 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
539 /* mark the packet as signed - BEFORE we sign it...*/
540 mark_packet_signed(outbuf);
542 /* I wonder what BSRSPYL stands for - but this is what MS
543 actually sends! */
544 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
545 return;
548 /***********************************************************
549 SMB signing - TEMP implementation - check a MAC sent by server.
550 ************************************************************/
552 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
554 return True;
557 /***********************************************************
558 SMB signing - TEMP implementation - free signing context
559 ************************************************************/
561 static void temp_free_signing_context(struct smb_sign_info *si)
563 return;
566 /***********************************************************
567 SMB signing - NULL implementation - setup the MAC key.
568 ************************************************************/
570 BOOL cli_null_set_signing(struct cli_state *cli)
572 return null_set_signing(&cli->sign_info);
575 /***********************************************************
576 SMB signing - temp implementation - setup the MAC key.
577 ************************************************************/
579 BOOL cli_temp_set_signing(struct cli_state *cli)
581 if (!cli_set_smb_signing_common(cli)) {
582 return False;
585 cli->sign_info.signing_context = NULL;
587 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
588 cli->sign_info.check_incoming_message = temp_check_incoming_message;
589 cli->sign_info.free_signing_context = temp_free_signing_context;
591 return True;
594 void cli_free_signing_context(struct cli_state *cli)
596 free_signing_context(&cli->sign_info);
600 * Sign a packet with the current mechanism
603 void cli_calculate_sign_mac(struct cli_state *cli)
605 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
609 * Check a packet with the current mechanism
610 * @return False if we had an established signing connection
611 * which had a bad checksum, True otherwise.
614 BOOL cli_check_sign_mac(struct cli_state *cli, BOOL must_be_ok)
616 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, must_be_ok)) {
617 free_signing_context(&cli->sign_info);
618 return False;
620 return True;
623 /***********************************************************
624 SMB signing - Server implementation - send the MAC.
625 ************************************************************/
627 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
629 unsigned char calc_md5_mac[16];
630 struct smb_basic_signing_context *data = si->signing_context;
631 uint32 send_seq_number = data->send_seq_num;
632 BOOL was_deferred_packet = False;
633 uint16 mid;
635 if (!si->doing_signing) {
636 return;
639 /* JRA Paranioa test - we should be able to get rid of this... */
640 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
641 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
642 smb_len(outbuf) ));
643 abort();
646 /* mark the packet as signed - BEFORE we sign it...*/
647 mark_packet_signed(outbuf);
649 mid = SVAL(outbuf, smb_mid);
651 /* See if this is a reply for a deferred packet. */
652 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
654 if (data->trans_info && (data->trans_info->mid == mid)) {
655 /* This is a reply in a trans stream. Use the sequence
656 * number associated with the stream mid. */
657 send_seq_number = data->trans_info->send_seq_num;
660 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
662 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
663 dump_data(10, (const char *)calc_md5_mac, 8);
665 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
667 /* cli->outbuf[smb_ss_field+2]=0;
668 Uncomment this to test if the remote client actually verifies signatures...*/
670 /* Don't mess with the sequence number for a deferred packet. */
671 if (was_deferred_packet) {
672 return;
675 if (!data->trans_info) {
676 /* Always increment if not in a trans stream. */
677 data->send_seq_num++;
678 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
679 /* Increment if this is the first reply in a trans stream or a
680 * packet that doesn't belong to this stream (different mid). */
681 data->send_seq_num++;
685 /***********************************************************
686 Is an incoming packet an oplock break reply ?
687 ************************************************************/
689 static BOOL is_oplock_break(char *inbuf)
691 if (CVAL(inbuf,smb_com) != SMBlockingX)
692 return False;
694 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
695 return False;
697 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
698 return True;
701 /***********************************************************
702 SMB signing - Server implementation - check a MAC sent by server.
703 ************************************************************/
705 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
707 BOOL good;
708 struct smb_basic_signing_context *data = si->signing_context;
709 uint32 reply_seq_number = data->send_seq_num;
710 uint32 saved_seq;
711 unsigned char calc_md5_mac[16];
712 unsigned char *server_sent_mac;
713 uint mid;
715 if (!si->doing_signing)
716 return True;
718 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
719 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
720 return False;
723 mid = SVAL(inbuf, smb_mid);
725 /* Is this part of a trans stream ? */
726 if (data->trans_info && (data->trans_info->mid == mid)) {
727 /* If so we don't increment the sequence. */
728 reply_seq_number = data->trans_info->reply_seq_num;
729 } else {
730 /* We always increment the sequence number. */
731 data->send_seq_num++;
733 /* If we get an asynchronous oplock break reply and there
734 * isn't a reply pending we need to re-sync the sequence
735 * number.
737 if (is_oplock_break(inbuf)) {
738 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
739 data->send_seq_num++;
743 saved_seq = reply_seq_number;
744 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
746 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
747 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
749 if (!good) {
751 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
752 (unsigned int)saved_seq));
753 dump_data(5, (const char *)calc_md5_mac, 8);
755 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
756 (unsigned int)saved_seq));
757 dump_data(5, (const char *)server_sent_mac, 8);
759 #if 1 /* JRATEST */
761 int i;
762 reply_seq_number -= 5;
763 for (i = 0; i < 10; i++, reply_seq_number++) {
764 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
765 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
766 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
767 We were expecting seq %u\n", reply_seq_number, saved_seq ));
768 break;
772 #endif /* JRATEST */
774 } else {
775 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));
776 dump_data(10, (const char *)server_sent_mac, 8);
779 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
782 /***********************************************************
783 SMB signing - server API's.
784 ************************************************************/
786 static struct smb_sign_info srv_sign_info = {
787 null_sign_outgoing_message,
788 null_check_incoming_message,
789 null_free_signing_context,
790 NULL,
791 False,
792 False,
793 False,
794 False
797 /***********************************************************
798 Turn signing off or on for oplock break code.
799 ************************************************************/
801 BOOL srv_oplock_set_signing(BOOL onoff)
803 BOOL ret = srv_sign_info.doing_signing;
804 srv_sign_info.doing_signing = onoff;
805 return ret;
808 /***********************************************************
809 Called to validate an incoming packet from the client.
810 ************************************************************/
812 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
814 /* Check if it's a session keepalive. */
815 if(CVAL(inbuf,0) == SMBkeepalive)
816 return True;
818 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
821 /***********************************************************
822 Called to sign an outgoing packet to the client.
823 ************************************************************/
825 void srv_calculate_sign_mac(char *outbuf)
827 /* Check if it's a session keepalive. */
828 /* JRA Paranioa test - do we ever generate these in the server ? */
829 if(CVAL(outbuf,0) == SMBkeepalive)
830 return;
832 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
835 /***********************************************************
836 Called by server to defer an outgoing packet.
837 ************************************************************/
839 void srv_defer_sign_response(uint16 mid)
841 struct smb_basic_signing_context *data;
843 if (!srv_sign_info.doing_signing)
844 return;
846 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
848 if (!data)
849 return;
851 store_sequence_for_reply(&data->outstanding_packet_list,
852 mid, data->send_seq_num);
853 data->send_seq_num++;
856 /***********************************************************
857 Called to remove sequence records when a deferred packet is
858 cancelled by mid. This should never find one....
859 ************************************************************/
861 void srv_cancel_sign_response(uint16 mid)
863 struct smb_basic_signing_context *data;
864 uint32 dummy_seq;
866 if (!srv_sign_info.doing_signing)
867 return;
869 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
871 if (!data)
872 return;
874 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
876 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
880 /***********************************************************
881 Called by server negprot when signing has been negotiated.
882 ************************************************************/
884 void srv_set_signing_negotiated(void)
886 srv_sign_info.allow_smb_signing = True;
887 srv_sign_info.negotiated_smb_signing = True;
888 if (lp_server_signing() == Required)
889 srv_sign_info.mandatory_signing = True;
891 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
892 srv_sign_info.check_incoming_message = temp_check_incoming_message;
893 srv_sign_info.free_signing_context = temp_free_signing_context;
896 /***********************************************************
897 Returns whether signing is active. We can't use sendfile or raw
898 reads/writes if it is.
899 ************************************************************/
901 BOOL srv_is_signing_active(void)
903 return srv_sign_info.doing_signing;
907 /***********************************************************
908 Returns whether signing is negotiated. We can't use it unless it was
909 in the negprot.
910 ************************************************************/
912 BOOL srv_is_signing_negotiated(void)
914 return srv_sign_info.negotiated_smb_signing;
917 /***********************************************************
918 Returns whether signing is negotiated. We can't use it unless it was
919 in the negprot.
920 ************************************************************/
922 BOOL srv_signing_started(void)
924 struct smb_basic_signing_context *data;
926 if (!srv_sign_info.doing_signing) {
927 return False;
930 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
931 if (!data)
932 return False;
934 if (data->send_seq_num == 0) {
935 return False;
938 return True;
942 /***********************************************************
943 Tell server code we are in a multiple trans reply state.
944 ************************************************************/
946 void srv_signing_trans_start(uint16 mid)
948 struct smb_basic_signing_context *data;
950 if (!srv_sign_info.doing_signing)
951 return;
953 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
954 if (!data)
955 return;
957 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
958 ZERO_STRUCTP(data->trans_info);
960 data->trans_info->reply_seq_num = data->send_seq_num-1;
961 data->trans_info->mid = mid;
962 data->trans_info->send_seq_num = data->send_seq_num;
964 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
965 data->send_seq_num = %u\n",
966 (unsigned int)mid,
967 (unsigned int)data->trans_info->reply_seq_num,
968 (unsigned int)data->trans_info->send_seq_num,
969 (unsigned int)data->send_seq_num ));
972 /***********************************************************
973 Tell server code we are out of a multiple trans reply state.
974 ************************************************************/
976 void srv_signing_trans_stop(void)
978 struct smb_basic_signing_context *data;
980 if (!srv_sign_info.doing_signing)
981 return;
983 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
984 if (!data || !data->trans_info)
985 return;
987 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
988 data->send_seq_num = %u\n",
989 (unsigned int)data->trans_info->mid,
990 (unsigned int)data->trans_info->reply_seq_num,
991 (unsigned int)data->trans_info->send_seq_num,
992 (unsigned int)data->send_seq_num ));
994 SAFE_FREE(data->trans_info);
995 data->trans_info = NULL;
998 /***********************************************************
999 Turn on signing from this packet onwards.
1000 ************************************************************/
1002 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1004 struct smb_basic_signing_context *data;
1006 if (!user_session_key.length)
1007 return;
1009 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1010 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1011 (unsigned int)srv_sign_info.negotiated_smb_signing,
1012 (unsigned int)srv_sign_info.mandatory_signing ));
1013 return;
1016 /* Once we've turned on, ignore any more sessionsetups. */
1017 if (srv_sign_info.doing_signing) {
1018 return;
1021 if (srv_sign_info.free_signing_context)
1022 srv_sign_info.free_signing_context(&srv_sign_info);
1024 srv_sign_info.doing_signing = True;
1026 data = smb_xmalloc(sizeof(*data));
1027 memset(data, '\0', sizeof(*data));
1029 srv_sign_info.signing_context = data;
1031 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1033 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1034 if (response.length)
1035 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1037 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1039 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1040 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1041 BOOLSTR(srv_sign_info.mandatory_signing) ));
1043 /* Initialise the sequence number */
1044 data->send_seq_num = 0;
1046 /* Initialise the list of outstanding packets */
1047 data->outstanding_packet_list = NULL;
1049 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1050 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1051 srv_sign_info.free_signing_context = simple_free_signing_context;