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 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));
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>.
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) {
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);
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) {
99 if (cli->sign_info.doing_signing) {
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;
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"));
129 static void mark_packet_signed(char *outbuf)
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
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)
158 /***********************************************************
159 SMB signing - NULL implementation - free signing context
160 ************************************************************/
162 static void null_free_signing_context(struct smb_sign_info *si)
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;
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)
202 if (good && !si->doing_signing) {
203 si->doing_signing = True;
207 if (si->doing_signing) {
208 struct smb_basic_signing_context *data = si->signing_context;
210 /* W2K sends a bad first signature but the sign engine is on.... JRA. */
211 if (data->send_seq_num > 1)
212 DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n",
213 (unsigned int)seq ));
217 DEBUG(3, ("signing_good: Peer did not sign reply correctly\n"));
218 free_signing_context(si);
225 /***********************************************************
226 SMB signing - Simple implementation - calculate a MAC on the packet
227 ************************************************************/
229 static void simple_packet_signature(struct smb_basic_signing_context *data,
230 const uchar *buf, uint32 seq_number,
231 unsigned char calc_md5_mac[16])
233 const size_t offset_end_of_sig = (smb_ss_field + 8);
234 unsigned char sequence_buf[8];
235 struct MD5Context md5_ctx;
238 * Firstly put the sequence number into the first 4 bytes.
239 * and zero out the next 4 bytes.
241 * We do this here, to avoid modifying the packet.
244 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
246 SIVAL(sequence_buf, 0, seq_number);
247 SIVAL(sequence_buf, 4, 0);
249 /* Calculate the 16 byte MAC - but don't alter the data in the
252 This makes for a bit of fussing about, but it's not too bad.
256 /* intialise with the key */
257 MD5Update(&md5_ctx, data->mac_key.data,
258 data->mac_key.length);
260 /* copy in the first bit of the SMB header */
261 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
263 /* copy in the sequence number, instead of the signature */
264 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
266 /* copy in the rest of the packet in, skipping the signature */
267 MD5Update(&md5_ctx, buf + offset_end_of_sig,
268 smb_len(buf) - (offset_end_of_sig - 4));
270 /* calculate the MD5 sig */
271 MD5Final(calc_md5_mac, &md5_ctx);
275 /***********************************************************
276 SMB signing - Client implementation - send the MAC.
277 ************************************************************/
279 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
281 unsigned char calc_md5_mac[16];
282 struct smb_basic_signing_context *data = si->signing_context;
285 if (!si->doing_signing)
288 /* JRA Paranioa test - we should be able to get rid of this... */
289 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
290 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
295 /* mark the packet as signed - BEFORE we sign it...*/
296 mark_packet_signed(outbuf);
298 if (data->trans_info)
299 send_seq_num = data->trans_info->send_seq_num;
301 send_seq_num = data->send_seq_num;
303 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
305 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
306 dump_data(10, (const char *)calc_md5_mac, 8);
308 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
310 /* cli->outbuf[smb_ss_field+2]=0;
311 Uncomment this to test if the remote server actually verifies signatures...*/
313 if (data->trans_info)
316 data->send_seq_num++;
317 store_sequence_for_reply(&data->outstanding_packet_list,
318 SVAL(outbuf,smb_mid), data->send_seq_num);
319 data->send_seq_num++;
322 /***********************************************************
323 SMB signing - Client implementation - check a MAC sent by server.
324 ************************************************************/
326 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
329 uint32 reply_seq_number;
331 unsigned char calc_md5_mac[16];
332 unsigned char *server_sent_mac;
334 struct smb_basic_signing_context *data = si->signing_context;
336 if (!si->doing_signing)
339 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
340 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
344 if (data->trans_info) {
345 reply_seq_number = data->trans_info->reply_seq_num;
346 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
347 SVAL(inbuf, smb_mid), &reply_seq_number)) {
348 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
349 (unsigned int) SVAL(inbuf, smb_mid) ));
353 saved_seq = reply_seq_number;
354 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
356 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
357 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
360 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
361 dump_data(5, (const char *)calc_md5_mac, 8);
363 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
364 dump_data(5, (const char *)server_sent_mac, 8);
368 reply_seq_number -= 5;
369 for (i = 0; i < 10; i++, reply_seq_number++) {
370 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
371 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
372 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
373 We were expecting seq %u\n", reply_seq_number, saved_seq ));
381 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
382 dump_data(10, (const char *)server_sent_mac, 8);
384 return signing_good(inbuf, si, good, saved_seq);
387 /***********************************************************
388 SMB signing - Simple implementation - free signing context
389 ************************************************************/
391 static void simple_free_signing_context(struct smb_sign_info *si)
393 struct smb_basic_signing_context *data = si->signing_context;
394 struct outstanding_packet_lookup *list = data->outstanding_packet_list;
397 struct outstanding_packet_lookup *old_head = list;
398 DLIST_REMOVE(list, list);
402 data_blob_free(&data->mac_key);
404 if (data->trans_info)
405 SAFE_FREE(data->trans_info);
407 SAFE_FREE(si->signing_context);
412 /***********************************************************
413 SMB signing - Simple implementation - setup the MAC key.
414 ************************************************************/
416 BOOL cli_simple_set_signing(struct cli_state *cli,
417 const DATA_BLOB user_session_key,
418 const DATA_BLOB response, int initial_send_seq_num)
420 struct smb_basic_signing_context *data;
422 if (!user_session_key.length)
425 if (!cli_set_smb_signing_common(cli)) {
429 if (!set_smb_signing_real_common(&cli->sign_info)) {
433 data = smb_xmalloc(sizeof(*data));
434 memset(data, '\0', sizeof(*data));
436 cli->sign_info.signing_context = data;
438 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
440 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
442 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
443 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
445 if (response.length) {
446 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
447 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
448 dump_data(10, (const char *)response.data, response.length);
450 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
453 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
455 /* Initialise the sequence number */
456 data->send_seq_num = initial_send_seq_num;
458 /* Initialise the list of outstanding packets */
459 data->outstanding_packet_list = NULL;
461 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
462 cli->sign_info.check_incoming_message = client_check_incoming_message;
463 cli->sign_info.free_signing_context = simple_free_signing_context;
468 /***********************************************************
469 Tell client code we are in a multiple trans reply state.
470 We call this after the last outgoing trans2 packet (which
471 has incremented the sequence numbers), so we must save the
472 current mid and sequence number -2.
473 ************************************************************/
475 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
477 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
479 if (!cli->sign_info.doing_signing || !data)
482 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
483 ZERO_STRUCTP(data->trans_info);
485 data->trans_info->send_seq_num = data->send_seq_num-2;
486 data->trans_info->mid = mid;
487 data->trans_info->reply_seq_num = data->send_seq_num-1;
489 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
490 data->send_seq_num = %u\n",
491 (unsigned int)data->trans_info->mid,
492 (unsigned int)data->trans_info->reply_seq_num,
493 (unsigned int)data->trans_info->send_seq_num,
494 (unsigned int)data->send_seq_num ));
497 /***********************************************************
498 Tell client code we are out of a multiple trans reply state.
499 ************************************************************/
501 void cli_signing_trans_stop(struct cli_state *cli)
503 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
505 if (!cli->sign_info.doing_signing || !data)
508 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
509 data->send_seq_num = %u\n",
510 (unsigned int)data->trans_info->mid,
511 (unsigned int)data->trans_info->reply_seq_num,
512 (unsigned int)data->trans_info->send_seq_num,
513 (unsigned int)data->send_seq_num ));
515 SAFE_FREE(data->trans_info);
516 data->trans_info = NULL;
519 /***********************************************************
520 SMB signing - TEMP implementation - calculate a MAC to send.
521 ************************************************************/
523 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
525 /* mark the packet as signed - BEFORE we sign it...*/
526 mark_packet_signed(outbuf);
528 /* I wonder what BSRSPYL stands for - but this is what MS
530 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
534 /***********************************************************
535 SMB signing - TEMP implementation - check a MAC sent by server.
536 ************************************************************/
538 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
543 /***********************************************************
544 SMB signing - TEMP implementation - free signing context
545 ************************************************************/
547 static void temp_free_signing_context(struct smb_sign_info *si)
552 /***********************************************************
553 SMB signing - NULL implementation - setup the MAC key.
554 ************************************************************/
556 BOOL cli_null_set_signing(struct cli_state *cli)
558 return null_set_signing(&cli->sign_info);
561 /***********************************************************
562 SMB signing - temp implementation - setup the MAC key.
563 ************************************************************/
565 BOOL cli_temp_set_signing(struct cli_state *cli)
567 if (!cli_set_smb_signing_common(cli)) {
571 cli->sign_info.signing_context = NULL;
573 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
574 cli->sign_info.check_incoming_message = temp_check_incoming_message;
575 cli->sign_info.free_signing_context = temp_free_signing_context;
580 void cli_free_signing_context(struct cli_state *cli)
582 free_signing_context(&cli->sign_info);
586 * Sign a packet with the current mechanism
589 void cli_calculate_sign_mac(struct cli_state *cli)
591 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
595 * Check a packet with the current mechanism
596 * @return False if we had an established signing connection
597 * which had a bad checksum, True otherwise.
600 BOOL cli_check_sign_mac(struct cli_state *cli)
602 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) {
603 free_signing_context(&cli->sign_info);
609 /***********************************************************
610 SMB signing - Server implementation - send the MAC.
611 ************************************************************/
613 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
615 unsigned char calc_md5_mac[16];
616 struct smb_basic_signing_context *data = si->signing_context;
617 uint32 send_seq_number = data->send_seq_num;
618 BOOL was_deferred_packet = False;
621 if (!si->doing_signing) {
625 /* JRA Paranioa test - we should be able to get rid of this... */
626 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
627 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
632 /* mark the packet as signed - BEFORE we sign it...*/
633 mark_packet_signed(outbuf);
635 mid = SVAL(outbuf, smb_mid);
637 /* See if this is a reply for a deferred packet. */
638 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
640 if (data->trans_info && (data->trans_info->mid == mid)) {
641 /* This is a reply in a trans stream. Use the sequence
642 * number associated with the stream mid. */
643 send_seq_number = data->trans_info->send_seq_num;
646 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
648 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
649 dump_data(10, (const char *)calc_md5_mac, 8);
651 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
653 /* cli->outbuf[smb_ss_field+2]=0;
654 Uncomment this to test if the remote client actually verifies signatures...*/
656 /* Don't mess with the sequence number for a deferred packet. */
657 if (was_deferred_packet) {
661 if (!data->trans_info) {
662 /* Always increment if not in a trans stream. */
663 data->send_seq_num++;
664 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
665 /* Increment if this is the first reply in a trans stream or a
666 * packet that doesn't belong to this stream (different mid). */
667 data->send_seq_num++;
671 /***********************************************************
672 Is an incoming packet an oplock break reply ?
673 ************************************************************/
675 static BOOL is_oplock_break(char *inbuf)
677 if (CVAL(inbuf,smb_com) != SMBlockingX)
680 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
683 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
687 /***********************************************************
688 SMB signing - Server implementation - check a MAC sent by server.
689 ************************************************************/
691 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
694 struct smb_basic_signing_context *data = si->signing_context;
695 uint32 reply_seq_number = data->send_seq_num;
697 unsigned char calc_md5_mac[16];
698 unsigned char *server_sent_mac;
701 if (!si->doing_signing)
704 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
705 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
709 mid = SVAL(inbuf, smb_mid);
711 /* Is this part of a trans stream ? */
712 if (data->trans_info && (data->trans_info->mid == mid)) {
713 /* If so we don't increment the sequence. */
714 reply_seq_number = data->trans_info->reply_seq_num;
716 /* We always increment the sequence number. */
717 data->send_seq_num++;
719 /* If we get an asynchronous oplock break reply and there
720 * isn't a reply pending we need to re-sync the sequence
723 if (is_oplock_break(inbuf)) {
724 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
725 data->send_seq_num++;
729 saved_seq = reply_seq_number;
730 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
732 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
733 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
737 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
738 (unsigned int)saved_seq));
739 dump_data(5, (const char *)calc_md5_mac, 8);
741 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
742 (unsigned int)saved_seq));
743 dump_data(5, (const char *)server_sent_mac, 8);
748 reply_seq_number -= 5;
749 for (i = 0; i < 10; i++, reply_seq_number++) {
750 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
751 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
752 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
753 We were expecting seq %u\n", reply_seq_number, saved_seq ));
761 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));
762 dump_data(10, (const char *)server_sent_mac, 8);
765 if (!signing_good(inbuf, si, good, saved_seq)) {
766 if (!si->mandatory_signing && (data->send_seq_num < 3)){
767 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
768 DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and client \
769 isn't sending correct signatures. Turning off.\n"));
770 si->negotiated_smb_signing = False;
771 si->allow_smb_signing = False;
772 si->doing_signing = False;
773 free_signing_context(si);
776 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
778 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u\n", (unsigned int)saved_seq));
786 /***********************************************************
787 SMB signing - server API's.
788 ************************************************************/
790 static struct smb_sign_info srv_sign_info = {
791 null_sign_outgoing_message,
792 null_check_incoming_message,
793 null_free_signing_context,
801 /***********************************************************
802 Turn signing off or on for oplock break code.
803 ************************************************************/
805 BOOL srv_oplock_set_signing(BOOL onoff)
807 BOOL ret = srv_sign_info.doing_signing;
808 srv_sign_info.doing_signing = onoff;
812 /***********************************************************
813 Called to validate an incoming packet from the client.
814 ************************************************************/
816 BOOL srv_check_sign_mac(char *inbuf)
818 /* Check if it's a session keepalive. */
819 if(CVAL(inbuf,0) == SMBkeepalive)
822 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info);
825 /***********************************************************
826 Called to sign an outgoing packet to the client.
827 ************************************************************/
829 void srv_calculate_sign_mac(char *outbuf)
831 /* Check if it's a session keepalive. */
832 /* JRA Paranioa test - do we ever generate these in the server ? */
833 if(CVAL(outbuf,0) == SMBkeepalive)
836 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
839 /***********************************************************
840 Called by server to defer an outgoing packet.
841 ************************************************************/
843 void srv_defer_sign_response(uint16 mid)
845 struct smb_basic_signing_context *data;
847 if (!srv_sign_info.doing_signing)
850 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
855 store_sequence_for_reply(&data->outstanding_packet_list,
856 mid, data->send_seq_num);
857 data->send_seq_num++;
860 /***********************************************************
861 Called to remove sequence records when a deferred packet is
862 cancelled by mid. This should never find one....
863 ************************************************************/
865 void srv_cancel_sign_response(uint16 mid)
867 struct smb_basic_signing_context *data;
870 if (!srv_sign_info.doing_signing)
873 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
878 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
880 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
884 /***********************************************************
885 Called by server negprot when signing has been negotiated.
886 ************************************************************/
888 void srv_set_signing_negotiated(void)
890 srv_sign_info.allow_smb_signing = True;
891 srv_sign_info.negotiated_smb_signing = True;
892 if (lp_server_signing() == Required)
893 srv_sign_info.mandatory_signing = True;
895 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
896 srv_sign_info.check_incoming_message = temp_check_incoming_message;
897 srv_sign_info.free_signing_context = temp_free_signing_context;
900 /***********************************************************
901 Returns whether signing is active. We can't use sendfile or raw
902 reads/writes if it is.
903 ************************************************************/
905 BOOL srv_is_signing_active(void)
907 return srv_sign_info.doing_signing;
910 /***********************************************************
911 Tell server code we are in a multiple trans reply state.
912 ************************************************************/
914 void srv_signing_trans_start(uint16 mid)
916 struct smb_basic_signing_context *data;
918 if (!srv_sign_info.doing_signing)
921 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
925 data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
926 ZERO_STRUCTP(data->trans_info);
928 data->trans_info->reply_seq_num = data->send_seq_num-1;
929 data->trans_info->mid = mid;
930 data->trans_info->send_seq_num = data->send_seq_num;
932 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
933 data->send_seq_num = %u\n",
935 (unsigned int)data->trans_info->reply_seq_num,
936 (unsigned int)data->trans_info->send_seq_num,
937 (unsigned int)data->send_seq_num ));
940 /***********************************************************
941 Tell server code we are out of a multiple trans reply state.
942 ************************************************************/
944 void srv_signing_trans_stop(void)
946 struct smb_basic_signing_context *data;
948 if (!srv_sign_info.doing_signing)
951 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
952 if (!data || !data->trans_info)
955 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
956 data->send_seq_num = %u\n",
957 (unsigned int)data->trans_info->mid,
958 (unsigned int)data->trans_info->reply_seq_num,
959 (unsigned int)data->trans_info->send_seq_num,
960 (unsigned int)data->send_seq_num ));
962 SAFE_FREE(data->trans_info);
963 data->trans_info = NULL;
966 /***********************************************************
967 Turn on signing from this packet onwards.
968 ************************************************************/
970 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
972 struct smb_basic_signing_context *data;
974 if (!user_session_key.length)
977 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
978 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
979 (unsigned int)srv_sign_info.negotiated_smb_signing,
980 (unsigned int)srv_sign_info.mandatory_signing ));
984 /* Once we've turned on, ignore any more sessionsetups. */
985 if (srv_sign_info.doing_signing) {
989 if (srv_sign_info.free_signing_context)
990 srv_sign_info.free_signing_context(&srv_sign_info);
992 srv_sign_info.doing_signing = True;
994 data = smb_xmalloc(sizeof(*data));
995 memset(data, '\0', sizeof(*data));
997 srv_sign_info.signing_context = data;
999 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1001 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1002 if (response.length)
1003 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1005 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1007 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1008 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1009 BOOLSTR(srv_sign_info.mandatory_signing) ));
1011 /* Initialise the sequence number */
1012 data->send_seq_num = 0;
1014 /* Initialise the list of outstanding packets */
1015 data->outstanding_packet_list = NULL;
1017 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1018 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1019 srv_sign_info.free_signing_context = simple_free_signing_context;