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;
258 unsigned char key_buf[16];
261 * Firstly put the sequence number into the first 4 bytes.
262 * and zero out the next 4 bytes.
264 * We do this here, to avoid modifying the packet.
267 DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
269 SIVAL(sequence_buf, 0, seq_number);
270 SIVAL(sequence_buf, 4, 0);
272 /* Calculate the 16 byte MAC - but don't alter the data in the
275 This makes for a bit of fussing about, but it's not too bad.
279 /* intialise with the key */
280 MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length);
282 /* JRA - apparently this is incorrect. */
283 /* NB. When making and verifying SMB signatures, Windows apparently
284 zero-pads the key to 128 bits if it isn't long enough.
285 From Nalin Dahyabhai <nalin@redhat.com> */
286 if (data->mac_key.length < sizeof(key_buf)) {
287 memset(key_buf, 0, sizeof(key_buf));
288 MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length);
292 /* copy in the first bit of the SMB header */
293 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
295 /* copy in the sequence number, instead of the signature */
296 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
298 /* copy in the rest of the packet in, skipping the signature */
299 MD5Update(&md5_ctx, buf + offset_end_of_sig,
300 smb_len(buf) - (offset_end_of_sig - 4));
302 /* calculate the MD5 sig */
303 MD5Final(calc_md5_mac, &md5_ctx);
307 /***********************************************************
308 SMB signing - Client implementation - send the MAC.
309 ************************************************************/
311 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
313 unsigned char calc_md5_mac[16];
314 struct smb_basic_signing_context *data = si->signing_context;
317 if (!si->doing_signing)
320 /* JRA Paranioa test - we should be able to get rid of this... */
321 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
322 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
327 /* mark the packet as signed - BEFORE we sign it...*/
328 mark_packet_signed(outbuf);
330 if (data->trans_info)
331 send_seq_num = data->trans_info->send_seq_num;
333 send_seq_num = data->send_seq_num;
335 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
337 DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
338 dump_data(10, (const char *)calc_md5_mac, 8);
340 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
342 /* cli->outbuf[smb_ss_field+2]=0;
343 Uncomment this to test if the remote server actually verifies signatures...*/
345 if (data->trans_info)
348 data->send_seq_num++;
349 store_sequence_for_reply(&data->outstanding_packet_list,
350 SVAL(outbuf,smb_mid), data->send_seq_num);
351 data->send_seq_num++;
354 /***********************************************************
355 SMB signing - Client implementation - check a MAC sent by server.
356 ************************************************************/
358 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
361 uint32 reply_seq_number;
363 unsigned char calc_md5_mac[16];
364 unsigned char *server_sent_mac;
366 struct smb_basic_signing_context *data = si->signing_context;
368 if (!si->doing_signing)
371 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
372 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
376 if (data->trans_info) {
377 reply_seq_number = data->trans_info->reply_seq_num;
378 } else if (!get_sequence_for_reply(&data->outstanding_packet_list,
379 SVAL(inbuf, smb_mid), &reply_seq_number)) {
380 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
381 (unsigned int) SVAL(inbuf, smb_mid) ));
385 saved_seq = reply_seq_number;
386 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
388 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
389 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
392 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
393 dump_data(5, (const char *)calc_md5_mac, 8);
395 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
396 dump_data(5, (const char *)server_sent_mac, 8);
400 reply_seq_number -= 5;
401 for (i = 0; i < 10; i++, reply_seq_number++) {
402 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
403 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
404 DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
405 We were expecting seq %u\n", reply_seq_number, saved_seq ));
413 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
414 dump_data(10, (const char *)server_sent_mac, 8);
416 return signing_good(inbuf, si, good, saved_seq, must_be_ok);
419 /***********************************************************
420 SMB signing - Simple implementation - free signing context
421 ************************************************************/
423 static void simple_free_signing_context(struct smb_sign_info *si)
425 struct smb_basic_signing_context *data = si->signing_context;
426 struct outstanding_packet_lookup *list = data->outstanding_packet_list;
429 struct outstanding_packet_lookup *old_head = list;
430 DLIST_REMOVE(list, list);
434 data_blob_free(&data->mac_key);
436 if (data->trans_info)
437 SAFE_FREE(data->trans_info);
439 SAFE_FREE(si->signing_context);
444 /***********************************************************
445 SMB signing - Simple implementation - setup the MAC key.
446 ************************************************************/
448 BOOL cli_simple_set_signing(struct cli_state *cli,
449 const DATA_BLOB user_session_key,
450 const DATA_BLOB response)
452 struct smb_basic_signing_context *data;
454 if (!user_session_key.length)
457 if (!cli_set_smb_signing_common(cli)) {
461 if (!set_smb_signing_real_common(&cli->sign_info)) {
465 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
466 memset(data, '\0', sizeof(*data));
468 cli->sign_info.signing_context = data;
470 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
472 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
474 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
475 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
477 if (response.length) {
478 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
479 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
480 dump_data(10, (const char *)response.data, response.length);
482 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
485 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
487 /* Initialise the sequence number */
488 data->send_seq_num = 0;
490 /* Initialise the list of outstanding packets */
491 data->outstanding_packet_list = NULL;
493 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
494 cli->sign_info.check_incoming_message = client_check_incoming_message;
495 cli->sign_info.free_signing_context = simple_free_signing_context;
500 /***********************************************************
501 Tell client code we are in a multiple trans reply state.
502 We call this after the last outgoing trans2 packet (which
503 has incremented the sequence numbers), so we must save the
504 current mid and sequence number -2.
505 ************************************************************/
507 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
509 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
510 uint32 reply_seq_num;
512 if (!cli->sign_info.doing_signing || !data)
515 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
516 ZERO_STRUCTP(data->trans_info);
518 /* This ensures the sequence is pulled off the outstanding packet list */
519 if (!get_sequence_for_reply(&data->outstanding_packet_list,
520 mid, &reply_seq_num)) {
521 DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
525 data->trans_info->send_seq_num = reply_seq_num - 1;
526 data->trans_info->mid = mid;
527 data->trans_info->reply_seq_num = reply_seq_num;
529 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
530 data->send_seq_num = %u\n",
531 (unsigned int)data->trans_info->mid,
532 (unsigned int)data->trans_info->reply_seq_num,
533 (unsigned int)data->trans_info->send_seq_num,
534 (unsigned int)data->send_seq_num ));
537 /***********************************************************
538 Tell client code we are out of a multiple trans reply state.
539 ************************************************************/
541 void cli_signing_trans_stop(struct cli_state *cli)
543 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
545 if (!cli->sign_info.doing_signing || !data)
548 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
549 data->send_seq_num = %u\n",
550 (unsigned int)data->trans_info->mid,
551 (unsigned int)data->trans_info->reply_seq_num,
552 (unsigned int)data->trans_info->send_seq_num,
553 (unsigned int)data->send_seq_num ));
555 SAFE_FREE(data->trans_info);
556 data->trans_info = NULL;
559 /***********************************************************
560 SMB signing - TEMP implementation - calculate a MAC to send.
561 ************************************************************/
563 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
565 /* mark the packet as signed - BEFORE we sign it...*/
566 mark_packet_signed(outbuf);
568 /* I wonder what BSRSPYL stands for - but this is what MS
570 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
574 /***********************************************************
575 SMB signing - TEMP implementation - check a MAC sent by server.
576 ************************************************************/
578 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
583 /***********************************************************
584 SMB signing - TEMP implementation - free signing context
585 ************************************************************/
587 static void temp_free_signing_context(struct smb_sign_info *si)
592 /***********************************************************
593 SMB signing - NULL implementation - setup the MAC key.
594 ************************************************************/
596 BOOL cli_null_set_signing(struct cli_state *cli)
598 return null_set_signing(&cli->sign_info);
601 /***********************************************************
602 SMB signing - temp implementation - setup the MAC key.
603 ************************************************************/
605 BOOL cli_temp_set_signing(struct cli_state *cli)
607 if (!cli_set_smb_signing_common(cli)) {
611 cli->sign_info.signing_context = NULL;
613 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
614 cli->sign_info.check_incoming_message = temp_check_incoming_message;
615 cli->sign_info.free_signing_context = temp_free_signing_context;
620 void cli_free_signing_context(struct cli_state *cli)
622 free_signing_context(&cli->sign_info);
626 * Sign a packet with the current mechanism
629 void cli_calculate_sign_mac(struct cli_state *cli)
631 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
635 * Check a packet with the current mechanism
636 * @return False if we had an established signing connection
637 * which had a bad checksum, True otherwise.
640 BOOL cli_check_sign_mac(struct cli_state *cli)
642 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
643 free_signing_context(&cli->sign_info);
649 /***********************************************************
650 SMB signing - Server implementation - send the MAC.
651 ************************************************************/
653 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
655 unsigned char calc_md5_mac[16];
656 struct smb_basic_signing_context *data = si->signing_context;
657 uint32 send_seq_number = data->send_seq_num;
658 BOOL was_deferred_packet = False;
661 if (!si->doing_signing) {
665 /* JRA Paranioa test - we should be able to get rid of this... */
666 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
667 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
672 /* mark the packet as signed - BEFORE we sign it...*/
673 mark_packet_signed(outbuf);
675 mid = SVAL(outbuf, smb_mid);
677 /* See if this is a reply for a deferred packet. */
678 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
680 if (data->trans_info && (data->trans_info->mid == mid)) {
681 /* This is a reply in a trans stream. Use the sequence
682 * number associated with the stream mid. */
683 send_seq_number = data->trans_info->send_seq_num;
686 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
688 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
689 dump_data(10, (const char *)calc_md5_mac, 8);
691 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
693 /* cli->outbuf[smb_ss_field+2]=0;
694 Uncomment this to test if the remote client actually verifies signatures...*/
696 /* Don't mess with the sequence number for a deferred packet. */
697 if (was_deferred_packet) {
701 if (!data->trans_info) {
702 /* Always increment if not in a trans stream. */
703 data->send_seq_num++;
704 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
705 /* Increment if this is the first reply in a trans stream or a
706 * packet that doesn't belong to this stream (different mid). */
707 data->send_seq_num++;
711 /***********************************************************
712 Is an incoming packet an oplock break reply ?
713 ************************************************************/
715 static BOOL is_oplock_break(char *inbuf)
717 if (CVAL(inbuf,smb_com) != SMBlockingX)
720 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
723 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
727 /***********************************************************
728 SMB signing - Server implementation - check a MAC sent by server.
729 ************************************************************/
731 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
734 struct smb_basic_signing_context *data = si->signing_context;
735 uint32 reply_seq_number = data->send_seq_num;
737 unsigned char calc_md5_mac[16];
738 unsigned char *server_sent_mac;
741 if (!si->doing_signing)
744 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
745 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
749 mid = SVAL(inbuf, smb_mid);
751 /* Is this part of a trans stream ? */
752 if (data->trans_info && (data->trans_info->mid == mid)) {
753 /* If so we don't increment the sequence. */
754 reply_seq_number = data->trans_info->reply_seq_num;
756 /* We always increment the sequence number. */
757 data->send_seq_num++;
759 /* If we get an asynchronous oplock break reply and there
760 * isn't a reply pending we need to re-sync the sequence
763 if (is_oplock_break(inbuf)) {
764 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
765 data->send_seq_num++;
769 saved_seq = reply_seq_number;
770 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
772 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
773 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
778 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
779 (unsigned int)saved_seq));
780 dump_data(5, (const char *)calc_md5_mac, 8);
782 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
783 (unsigned int)reply_seq_number));
784 dump_data(5, (const char *)server_sent_mac, 8);
790 reply_seq_number -= 5;
791 for (i = 0; i < 10; i++, reply_seq_number++) {
792 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
793 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
794 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
795 We were expecting seq %u\n", reply_seq_number, saved_seq ));
803 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));
804 dump_data(10, (const char *)server_sent_mac, 8);
807 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
810 /***********************************************************
811 SMB signing - server API's.
812 ************************************************************/
814 static struct smb_sign_info srv_sign_info = {
815 null_sign_outgoing_message,
816 null_check_incoming_message,
817 null_free_signing_context,
825 /***********************************************************
826 Turn signing off or on for oplock break code.
827 ************************************************************/
829 BOOL srv_oplock_set_signing(BOOL onoff)
831 BOOL ret = srv_sign_info.doing_signing;
832 srv_sign_info.doing_signing = onoff;
836 /***********************************************************
837 Called to validate an incoming packet from the client.
838 ************************************************************/
840 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
842 /* Check if it's a session keepalive. */
843 if(CVAL(inbuf,0) == SMBkeepalive)
846 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
849 /***********************************************************
850 Called to sign an outgoing packet to the client.
851 ************************************************************/
853 void srv_calculate_sign_mac(char *outbuf)
855 /* Check if it's a session keepalive. */
856 /* JRA Paranioa test - do we ever generate these in the server ? */
857 if(CVAL(outbuf,0) == SMBkeepalive)
860 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
863 /***********************************************************
864 Called by server to defer an outgoing packet.
865 ************************************************************/
867 void srv_defer_sign_response(uint16 mid)
869 struct smb_basic_signing_context *data;
871 if (!srv_sign_info.doing_signing)
874 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
880 * Ensure we only store this mid reply once...
883 if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
884 data->send_seq_num++;
888 /***********************************************************
889 Called to remove sequence records when a deferred packet is
890 cancelled by mid. This should never find one....
891 ************************************************************/
893 void srv_cancel_sign_response(uint16 mid)
895 struct smb_basic_signing_context *data;
898 if (!srv_sign_info.doing_signing)
901 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
906 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
908 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
912 /***********************************************************
913 Called by server negprot when signing has been negotiated.
914 ************************************************************/
916 void srv_set_signing_negotiated(void)
918 srv_sign_info.allow_smb_signing = True;
919 srv_sign_info.negotiated_smb_signing = True;
920 if (lp_server_signing() == Required)
921 srv_sign_info.mandatory_signing = True;
923 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
924 srv_sign_info.check_incoming_message = temp_check_incoming_message;
925 srv_sign_info.free_signing_context = temp_free_signing_context;
928 /***********************************************************
929 Returns whether signing is active. We can't use sendfile or raw
930 reads/writes if it is.
931 ************************************************************/
933 BOOL srv_is_signing_active(void)
935 return srv_sign_info.doing_signing;
939 /***********************************************************
940 Returns whether signing is negotiated. We can't use it unless it was
942 ************************************************************/
944 BOOL srv_is_signing_negotiated(void)
946 return srv_sign_info.negotiated_smb_signing;
949 /***********************************************************
950 Returns whether signing is actually happening
951 ************************************************************/
953 BOOL srv_signing_started(void)
955 struct smb_basic_signing_context *data;
957 if (!srv_sign_info.doing_signing) {
961 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
965 if (data->send_seq_num == 0) {
973 /***********************************************************
974 Tell server code we are in a multiple trans reply state.
975 ************************************************************/
977 void srv_signing_trans_start(uint16 mid)
979 struct smb_basic_signing_context *data;
981 if (!srv_sign_info.doing_signing)
984 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
988 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
989 ZERO_STRUCTP(data->trans_info);
991 data->trans_info->reply_seq_num = data->send_seq_num-1;
992 data->trans_info->mid = mid;
993 data->trans_info->send_seq_num = data->send_seq_num;
995 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
996 data->send_seq_num = %u\n",
998 (unsigned int)data->trans_info->reply_seq_num,
999 (unsigned int)data->trans_info->send_seq_num,
1000 (unsigned int)data->send_seq_num ));
1003 /***********************************************************
1004 Tell server code we are out of a multiple trans reply state.
1005 ************************************************************/
1007 void srv_signing_trans_stop(void)
1009 struct smb_basic_signing_context *data;
1011 if (!srv_sign_info.doing_signing)
1014 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1015 if (!data || !data->trans_info)
1018 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1019 data->send_seq_num = %u\n",
1020 (unsigned int)data->trans_info->mid,
1021 (unsigned int)data->trans_info->reply_seq_num,
1022 (unsigned int)data->trans_info->send_seq_num,
1023 (unsigned int)data->send_seq_num ));
1025 SAFE_FREE(data->trans_info);
1026 data->trans_info = NULL;
1029 /***********************************************************
1030 Turn on signing from this packet onwards.
1031 ************************************************************/
1033 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1035 struct smb_basic_signing_context *data;
1037 if (!user_session_key.length)
1040 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1041 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1042 (unsigned int)srv_sign_info.negotiated_smb_signing,
1043 (unsigned int)srv_sign_info.mandatory_signing ));
1047 /* Once we've turned on, ignore any more sessionsetups. */
1048 if (srv_sign_info.doing_signing) {
1052 if (srv_sign_info.free_signing_context)
1053 srv_sign_info.free_signing_context(&srv_sign_info);
1055 srv_sign_info.doing_signing = True;
1057 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
1058 memset(data, '\0', sizeof(*data));
1060 srv_sign_info.signing_context = data;
1062 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1064 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1065 if (response.length)
1066 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1068 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1070 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1071 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1072 BOOLSTR(srv_sign_info.mandatory_signing) ));
1074 /* Initialise the sequence number */
1075 data->send_seq_num = 0;
1077 /* Initialise the list of outstanding packets */
1078 data->outstanding_packet_list = NULL;
1080 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1081 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1082 srv_sign_info.free_signing_context = simple_free_signing_context;