2 Unix SMB/CIFS implementation.
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.
24 /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
25 struct outstanding_packet_lookup {
28 struct outstanding_packet_lookup *prev, *next;
31 /* Store the data for an ongoing trans/trans2/nttrans operation. */
32 struct trans_info_context {
38 struct smb_basic_signing_context {
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) {
57 t = SMB_XMALLOC_P(struct outstanding_packet_lookup);
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>.
73 DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
74 (unsigned int)reply_seq_num, (unsigned int)mid ));
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) {
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);
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) {
107 if (cli->sign_info.doing_signing) {
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;
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"));
137 static void mark_packet_signed(char *outbuf)
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
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)
166 /***********************************************************
167 SMB signing - NULL implementation - free signing context
168 ************************************************************/
170 static void null_free_signing_context(struct smb_sign_info *si)
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;
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)
212 if (!si->doing_signing) {
213 si->doing_signing = True;
216 if (!si->seen_valid) {
217 si->seen_valid = True;
221 if (!si->mandatory_signing && !si->seen_valid) {
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);
234 } else if (!must_be_ok) {
235 /* This packet is known to be unsigned */
238 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
240 DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
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;
259 /* JRA - apparently this is incorrect. */
260 unsigned char key_buf[16];
264 * Firstly put the sequence number into the first 4 bytes.
265 * and zero out the next 4 bytes.
267 * We do this here, to avoid modifying the packet.
270 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
272 SIVAL(sequence_buf, 0, seq_number);
273 SIVAL(sequence_buf, 4, 0);
275 /* Calculate the 16 byte MAC - but don't alter the data in the
278 This makes for a bit of fussing about, but it's not too bad.
282 /* intialise with the key */
283 MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length);
285 /* JRA - apparently this is incorrect. */
286 /* NB. When making and verifying SMB signatures, Windows apparently
287 zero-pads the key to 128 bits if it isn't long enough.
288 From Nalin Dahyabhai <nalin@redhat.com> */
289 if (data->mac_key.length < sizeof(key_buf)) {
290 memset(key_buf, 0, sizeof(key_buf));
291 MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length);
295 /* copy in the first bit of the SMB header */
296 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
298 /* copy in the sequence number, instead of the signature */
299 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
301 /* copy in the rest of the packet in, skipping the signature */
302 MD5Update(&md5_ctx, buf + offset_end_of_sig,
303 smb_len(buf) - (offset_end_of_sig - 4));
305 /* calculate the MD5 sig */
306 MD5Final(calc_md5_mac, &md5_ctx);
310 /***********************************************************
311 SMB signing - Client implementation - send the MAC.
312 ************************************************************/
314 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
316 unsigned char calc_md5_mac[16];
317 struct smb_basic_signing_context *data = si->signing_context;
320 if (!si->doing_signing)
323 /* JRA Paranioa test - we should be able to get rid of this... */
324 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
325 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
330 /* mark the packet as signed - BEFORE we sign it...*/
331 mark_packet_signed(outbuf);
333 if (data->trans_info)
334 send_seq_num = data->trans_info->send_seq_num;
336 send_seq_num = data->send_seq_num;
338 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
340 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
341 dump_data(10, (const char *)calc_md5_mac, 8);
343 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
345 /* cli->outbuf[smb_ss_field+2]=0;
346 Uncomment this to test if the remote server actually verifies signatures...*/
348 if (data->trans_info)
351 data->send_seq_num++;
352 store_sequence_for_reply(&data->outstanding_packet_list,
353 SVAL(outbuf,smb_mid), data->send_seq_num);
354 data->send_seq_num++;
357 /***********************************************************
358 SMB signing - Client implementation - check a MAC sent by server.
359 ************************************************************/
361 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
364 uint32 reply_seq_number;
366 unsigned char calc_md5_mac[16];
367 unsigned char *server_sent_mac;
369 struct smb_basic_signing_context *data = si->signing_context;
371 if (!si->doing_signing)
374 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
375 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
379 if (data->trans_info) {
380 reply_seq_number = data->trans_info->reply_seq_num;
381 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
382 SVAL(inbuf, smb_mid), &reply_seq_number)) {
383 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
384 (unsigned int) SVAL(inbuf, smb_mid) ));
388 saved_seq = reply_seq_number;
389 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
391 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
392 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
395 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
396 dump_data(5, (const char *)calc_md5_mac, 8);
398 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
399 dump_data(5, (const char *)server_sent_mac, 8);
403 reply_seq_number -= 5;
404 for (i = 0; i < 10; i++, reply_seq_number++) {
405 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
406 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
407 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
408 We were expecting seq %u\n", reply_seq_number, saved_seq ));
416 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
417 dump_data(10, (const char *)server_sent_mac, 8);
419 return signing_good(inbuf, si, good, saved_seq, must_be_ok);
422 /***********************************************************
423 SMB signing - Simple implementation - free signing context
424 ************************************************************/
426 static void simple_free_signing_context(struct smb_sign_info *si)
428 struct smb_basic_signing_context *data = si->signing_context;
429 struct outstanding_packet_lookup *list;
430 struct outstanding_packet_lookup *next;
432 for (list = data->outstanding_packet_list; list; list = next) {
434 DLIST_REMOVE(data->outstanding_packet_list, list);
438 data_blob_free(&data->mac_key);
440 if (data->trans_info) {
441 SAFE_FREE(data->trans_info);
444 SAFE_FREE(si->signing_context);
449 /***********************************************************
450 SMB signing - Simple implementation - setup the MAC key.
451 ************************************************************/
453 BOOL cli_simple_set_signing(struct cli_state *cli,
454 const DATA_BLOB user_session_key,
455 const DATA_BLOB response)
457 struct smb_basic_signing_context *data;
459 if (!user_session_key.length)
462 if (!cli_set_smb_signing_common(cli)) {
466 if (!set_smb_signing_real_common(&cli->sign_info)) {
470 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
471 memset(data, '\0', sizeof(*data));
473 cli->sign_info.signing_context = data;
475 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
477 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
479 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
480 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
482 if (response.length) {
483 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
484 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
485 dump_data(10, (const char *)response.data, response.length);
487 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
490 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
492 /* Initialise the sequence number */
493 data->send_seq_num = 0;
495 /* Initialise the list of outstanding packets */
496 data->outstanding_packet_list = NULL;
498 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
499 cli->sign_info.check_incoming_message = client_check_incoming_message;
500 cli->sign_info.free_signing_context = simple_free_signing_context;
505 /***********************************************************
506 Tell client code we are in a multiple trans reply state.
507 We call this after the last outgoing trans2 packet (which
508 has incremented the sequence numbers), so we must save the
509 current mid and sequence number -2.
510 ************************************************************/
512 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
514 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
515 uint32 reply_seq_num;
517 if (!cli->sign_info.doing_signing || !data)
520 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
521 ZERO_STRUCTP(data->trans_info);
523 /* This ensures the sequence is pulled off the outstanding packet list */
524 if (!get_sequence_for_reply(&data->outstanding_packet_list,
525 mid, &reply_seq_num)) {
526 DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
530 data->trans_info->send_seq_num = reply_seq_num - 1;
531 data->trans_info->mid = mid;
532 data->trans_info->reply_seq_num = reply_seq_num;
534 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
535 data->send_seq_num = %u\n",
536 (unsigned int)data->trans_info->mid,
537 (unsigned int)data->trans_info->reply_seq_num,
538 (unsigned int)data->trans_info->send_seq_num,
539 (unsigned int)data->send_seq_num ));
542 /***********************************************************
543 Tell client code we are out of a multiple trans reply state.
544 ************************************************************/
546 void cli_signing_trans_stop(struct cli_state *cli)
548 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
550 if (!cli->sign_info.doing_signing || !data)
553 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
554 data->send_seq_num = %u\n",
555 (unsigned int)data->trans_info->mid,
556 (unsigned int)data->trans_info->reply_seq_num,
557 (unsigned int)data->trans_info->send_seq_num,
558 (unsigned int)data->send_seq_num ));
560 SAFE_FREE(data->trans_info);
561 data->trans_info = NULL;
564 /***********************************************************
565 SMB signing - TEMP implementation - calculate a MAC to send.
566 ************************************************************/
568 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
570 /* mark the packet as signed - BEFORE we sign it...*/
571 mark_packet_signed(outbuf);
573 /* I wonder what BSRSPYL stands for - but this is what MS
575 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
579 /***********************************************************
580 SMB signing - TEMP implementation - check a MAC sent by server.
581 ************************************************************/
583 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
588 /***********************************************************
589 SMB signing - TEMP implementation - free signing context
590 ************************************************************/
592 static void temp_free_signing_context(struct smb_sign_info *si)
597 /***********************************************************
598 SMB signing - NULL implementation - setup the MAC key.
599 ************************************************************/
601 BOOL cli_null_set_signing(struct cli_state *cli)
603 return null_set_signing(&cli->sign_info);
606 /***********************************************************
607 SMB signing - temp implementation - setup the MAC key.
608 ************************************************************/
610 BOOL cli_temp_set_signing(struct cli_state *cli)
612 if (!cli_set_smb_signing_common(cli)) {
616 cli->sign_info.signing_context = NULL;
618 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
619 cli->sign_info.check_incoming_message = temp_check_incoming_message;
620 cli->sign_info.free_signing_context = temp_free_signing_context;
625 void cli_free_signing_context(struct cli_state *cli)
627 free_signing_context(&cli->sign_info);
631 * Sign a packet with the current mechanism
634 void cli_calculate_sign_mac(struct cli_state *cli)
636 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
640 * Check a packet with the current mechanism
641 * @return False if we had an established signing connection
642 * which had a bad checksum, True otherwise.
645 BOOL cli_check_sign_mac(struct cli_state *cli)
647 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
648 free_signing_context(&cli->sign_info);
654 /***********************************************************
655 SMB signing - Server implementation - send the MAC.
656 ************************************************************/
658 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
660 unsigned char calc_md5_mac[16];
661 struct smb_basic_signing_context *data = si->signing_context;
662 uint32 send_seq_number = data->send_seq_num;
663 BOOL was_deferred_packet = False;
666 if (!si->doing_signing) {
670 /* JRA Paranioa test - we should be able to get rid of this... */
671 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
672 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
677 /* mark the packet as signed - BEFORE we sign it...*/
678 mark_packet_signed(outbuf);
680 mid = SVAL(outbuf, smb_mid);
682 /* See if this is a reply for a deferred packet. */
683 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
685 if (data->trans_info && (data->trans_info->mid == mid)) {
686 /* This is a reply in a trans stream. Use the sequence
687 * number associated with the stream mid. */
688 send_seq_number = data->trans_info->send_seq_num;
691 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
693 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
694 dump_data(10, (const char *)calc_md5_mac, 8);
696 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
698 /* cli->outbuf[smb_ss_field+2]=0;
699 Uncomment this to test if the remote client actually verifies signatures...*/
701 /* Don't mess with the sequence number for a deferred packet. */
702 if (was_deferred_packet) {
706 if (!data->trans_info) {
707 /* Always increment if not in a trans stream. */
708 data->send_seq_num++;
709 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
710 /* Increment if this is the first reply in a trans stream or a
711 * packet that doesn't belong to this stream (different mid). */
712 data->send_seq_num++;
716 /***********************************************************
717 Is an incoming packet an oplock break reply ?
718 ************************************************************/
720 static BOOL is_oplock_break(char *inbuf)
722 if (CVAL(inbuf,smb_com) != SMBlockingX)
725 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
728 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
732 /***********************************************************
733 SMB signing - Server implementation - check a MAC sent by server.
734 ************************************************************/
736 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
739 struct smb_basic_signing_context *data = si->signing_context;
740 uint32 reply_seq_number = data->send_seq_num;
742 unsigned char calc_md5_mac[16];
743 unsigned char *server_sent_mac;
746 if (!si->doing_signing)
749 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
750 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
754 mid = SVAL(inbuf, smb_mid);
756 /* Is this part of a trans stream ? */
757 if (data->trans_info && (data->trans_info->mid == mid)) {
758 /* If so we don't increment the sequence. */
759 reply_seq_number = data->trans_info->reply_seq_num;
761 /* We always increment the sequence number. */
762 data->send_seq_num++;
764 /* If we get an asynchronous oplock break reply and there
765 * isn't a reply pending we need to re-sync the sequence
768 if (is_oplock_break(inbuf)) {
769 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
770 data->send_seq_num++;
774 saved_seq = reply_seq_number;
775 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
777 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
778 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
783 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
784 (unsigned int)saved_seq));
785 dump_data(5, (const char *)calc_md5_mac, 8);
787 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
788 (unsigned int)reply_seq_number));
789 dump_data(5, (const char *)server_sent_mac, 8);
795 reply_seq_number -= 5;
796 for (i = 0; i < 10; i++, reply_seq_number++) {
797 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
798 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
799 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
800 We were expecting seq %u\n", reply_seq_number, saved_seq ));
808 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));
809 dump_data(10, (const char *)server_sent_mac, 8);
812 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
815 /***********************************************************
816 SMB signing - server API's.
817 ************************************************************/
819 static struct smb_sign_info srv_sign_info = {
820 null_sign_outgoing_message,
821 null_check_incoming_message,
822 null_free_signing_context,
830 /***********************************************************
831 Turn signing off or on for oplock break code.
832 ************************************************************/
834 BOOL srv_oplock_set_signing(BOOL onoff)
836 BOOL ret = srv_sign_info.doing_signing;
837 srv_sign_info.doing_signing = onoff;
841 /***********************************************************
842 Called to validate an incoming packet from the client.
843 ************************************************************/
845 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
847 /* Check if it's a session keepalive. */
848 if(CVAL(inbuf,0) == SMBkeepalive)
851 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
854 /***********************************************************
855 Called to sign an outgoing packet to the client.
856 ************************************************************/
858 void srv_calculate_sign_mac(char *outbuf)
860 /* Check if it's a session keepalive. */
861 /* JRA Paranioa test - do we ever generate these in the server ? */
862 if(CVAL(outbuf,0) == SMBkeepalive)
865 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
868 /***********************************************************
869 Called by server to defer an outgoing packet.
870 ************************************************************/
872 void srv_defer_sign_response(uint16 mid)
874 struct smb_basic_signing_context *data;
876 if (!srv_sign_info.doing_signing)
879 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
885 * Ensure we only store this mid reply once...
888 if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
889 data->send_seq_num++;
893 /***********************************************************
894 Called to remove sequence records when a deferred packet is
895 cancelled by mid. This should never find one....
896 ************************************************************/
898 void srv_cancel_sign_response(uint16 mid)
900 struct smb_basic_signing_context *data;
903 if (!srv_sign_info.doing_signing)
906 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
911 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
913 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
917 /***********************************************************
918 Called by server negprot when signing has been negotiated.
919 ************************************************************/
921 void srv_set_signing_negotiated(void)
923 srv_sign_info.allow_smb_signing = True;
924 srv_sign_info.negotiated_smb_signing = True;
925 if (lp_server_signing() == Required)
926 srv_sign_info.mandatory_signing = True;
928 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
929 srv_sign_info.check_incoming_message = temp_check_incoming_message;
930 srv_sign_info.free_signing_context = temp_free_signing_context;
933 /***********************************************************
934 Returns whether signing is active. We can't use sendfile or raw
935 reads/writes if it is.
936 ************************************************************/
938 BOOL srv_is_signing_active(void)
940 return srv_sign_info.doing_signing;
944 /***********************************************************
945 Returns whether signing is negotiated. We can't use it unless it was
947 ************************************************************/
949 BOOL srv_is_signing_negotiated(void)
951 return srv_sign_info.negotiated_smb_signing;
954 /***********************************************************
955 Returns whether signing is actually happening
956 ************************************************************/
958 BOOL srv_signing_started(void)
960 struct smb_basic_signing_context *data;
962 if (!srv_sign_info.doing_signing) {
966 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
970 if (data->send_seq_num == 0) {
978 /***********************************************************
979 Tell server code we are in a multiple trans reply state.
980 ************************************************************/
982 void srv_signing_trans_start(uint16 mid)
984 struct smb_basic_signing_context *data;
986 if (!srv_sign_info.doing_signing)
989 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
993 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
994 ZERO_STRUCTP(data->trans_info);
996 data->trans_info->reply_seq_num = data->send_seq_num-1;
997 data->trans_info->mid = mid;
998 data->trans_info->send_seq_num = data->send_seq_num;
1000 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1001 data->send_seq_num = %u\n",
1003 (unsigned int)data->trans_info->reply_seq_num,
1004 (unsigned int)data->trans_info->send_seq_num,
1005 (unsigned int)data->send_seq_num ));
1008 /***********************************************************
1009 Tell server code we are out of a multiple trans reply state.
1010 ************************************************************/
1012 void srv_signing_trans_stop(void)
1014 struct smb_basic_signing_context *data;
1016 if (!srv_sign_info.doing_signing)
1019 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1020 if (!data || !data->trans_info)
1023 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1024 data->send_seq_num = %u\n",
1025 (unsigned int)data->trans_info->mid,
1026 (unsigned int)data->trans_info->reply_seq_num,
1027 (unsigned int)data->trans_info->send_seq_num,
1028 (unsigned int)data->send_seq_num ));
1030 SAFE_FREE(data->trans_info);
1031 data->trans_info = NULL;
1034 /***********************************************************
1035 Turn on signing from this packet onwards.
1036 ************************************************************/
1038 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1040 struct smb_basic_signing_context *data;
1042 if (!user_session_key.length)
1045 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1046 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1047 (unsigned int)srv_sign_info.negotiated_smb_signing,
1048 (unsigned int)srv_sign_info.mandatory_signing ));
1052 /* Once we've turned on, ignore any more sessionsetups. */
1053 if (srv_sign_info.doing_signing) {
1057 if (srv_sign_info.free_signing_context)
1058 srv_sign_info.free_signing_context(&srv_sign_info);
1060 srv_sign_info.doing_signing = True;
1062 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
1063 memset(data, '\0', sizeof(*data));
1065 srv_sign_info.signing_context = data;
1067 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1069 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1070 if (response.length)
1071 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1073 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1075 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1076 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1077 BOOLSTR(srv_sign_info.mandatory_signing) ));
1079 /* Initialise the sequence number */
1080 data->send_seq_num = 0;
1082 /* Initialise the list of outstanding packets */
1083 data->outstanding_packet_list = NULL;
1085 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1086 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1087 srv_sign_info.free_signing_context = simple_free_signing_context;