r14279: Fix coverity #86, 87, 88, 89:
[Samba/nascimento.git] / source3 / libsmb / smb_signing.c
blobf0f2024e7b9ff9f0ac477e36ddfb160d23c92732
1 /*
2 Unix SMB/CIFS implementation.
3 SMB Signing Code
4 Copyright (C) Jeremy Allison 2003.
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
25 struct outstanding_packet_lookup {
26 uint16 mid;
27 uint32 reply_seq_num;
28 struct outstanding_packet_lookup *prev, *next;
31 /* Store the data for an ongoing trans/trans2/nttrans operation. */
32 struct trans_info_context {
33 uint16 mid;
34 uint32 send_seq_num;
35 uint32 reply_seq_num;
38 struct smb_basic_signing_context {
39 DATA_BLOB mac_key;
40 uint32 send_seq_num;
41 struct trans_info_context *trans_info;
42 struct outstanding_packet_lookup *outstanding_packet_list;
45 static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list,
46 uint16 mid, uint32 reply_seq_num)
48 struct outstanding_packet_lookup *t;
50 /* Ensure we only add a mid once. */
51 for (t = *list; t; t = t->next) {
52 if (t->mid == mid) {
53 return False;
57 t = SMB_XMALLOC_P(struct outstanding_packet_lookup);
58 ZERO_STRUCTP(t);
60 t->mid = mid;
61 t->reply_seq_num = reply_seq_num;
64 * Add to the *start* of the list not the end of the list.
65 * This ensures that the *last* send sequence with this mid
66 * is returned by preference.
67 * This can happen if the mid wraps and one of the early
68 * mid numbers didn't get a reply and is still lurking on
69 * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>.
72 DLIST_ADD(*list, t);
73 DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
74 (unsigned int)reply_seq_num, (unsigned int)mid ));
75 return True;
78 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
79 uint16 mid, uint32 *reply_seq_num)
81 struct outstanding_packet_lookup *t;
83 for (t = *list; t; t = t->next) {
84 if (t->mid == mid) {
85 *reply_seq_num = t->reply_seq_num;
86 DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
87 (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
88 DLIST_REMOVE(*list, t);
89 SAFE_FREE(t);
90 return True;
93 return False;
96 /***********************************************************
97 SMB signing - Common code before we set a new signing implementation
98 ************************************************************/
100 static BOOL cli_set_smb_signing_common(struct cli_state *cli)
102 if (!cli->sign_info.negotiated_smb_signing
103 && !cli->sign_info.mandatory_signing) {
104 return False;
107 if (cli->sign_info.doing_signing) {
108 return False;
111 if (cli->sign_info.free_signing_context)
112 cli->sign_info.free_signing_context(&cli->sign_info);
114 /* These calls are INCOMPATIBLE with SMB signing */
115 cli->readbraw_supported = False;
116 cli->writebraw_supported = False;
118 return True;
121 /***********************************************************
122 SMB signing - Common code for 'real' implementations
123 ************************************************************/
125 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
127 if (si->mandatory_signing) {
128 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
131 si->doing_signing = True;
132 DEBUG(5, ("SMB signing enabled!\n"));
134 return True;
137 static void mark_packet_signed(char *outbuf)
139 uint16 flags2;
140 flags2 = SVAL(outbuf,smb_flg2);
141 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
142 SSVAL(outbuf,smb_flg2, flags2);
145 /***********************************************************
146 SMB signing - NULL implementation - calculate a MAC to send.
147 ************************************************************/
149 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
151 /* we can't zero out the sig, as we might be trying to send a
152 session request - which is NBT-level, not SMB level and doesn't
153 have the field */
154 return;
157 /***********************************************************
158 SMB signing - NULL implementation - check a MAC sent by server.
159 ************************************************************/
161 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
163 return True;
166 /***********************************************************
167 SMB signing - NULL implementation - free signing context
168 ************************************************************/
170 static void null_free_signing_context(struct smb_sign_info *si)
172 return;
176 SMB signing - NULL implementation - setup the MAC key.
178 @note Used as an initialisation only - it will not correctly
179 shut down a real signing mechanism
182 static BOOL null_set_signing(struct smb_sign_info *si)
184 si->signing_context = NULL;
186 si->sign_outgoing_message = null_sign_outgoing_message;
187 si->check_incoming_message = null_check_incoming_message;
188 si->free_signing_context = null_free_signing_context;
190 return True;
194 * Free the signing context
197 static void free_signing_context(struct smb_sign_info *si)
199 if (si->free_signing_context) {
200 si->free_signing_context(si);
201 si->signing_context = NULL;
204 null_set_signing(si);
208 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok)
210 if (good) {
212 if (!si->doing_signing) {
213 si->doing_signing = True;
216 if (!si->seen_valid) {
217 si->seen_valid = True;
220 } else {
221 if (!si->mandatory_signing && !si->seen_valid) {
223 if (!must_be_ok) {
224 return True;
226 /* Non-mandatory signing - just turn off if this is the first bad packet.. */
227 DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n"
228 "isn't sending correct signatures. Turning off.\n"));
229 si->negotiated_smb_signing = False;
230 si->allow_smb_signing = False;
231 si->doing_signing = False;
232 free_signing_context(si);
233 return True;
234 } else if (!must_be_ok) {
235 /* This packet is known to be unsigned */
236 return True;
237 } else {
238 /* Mandatory signing or bad packet after signing started - fail and disconnect. */
239 if (seq)
240 DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
241 return False;
244 return True;
247 /***********************************************************
248 SMB signing - Simple implementation - calculate a MAC on the packet
249 ************************************************************/
251 static void simple_packet_signature(struct smb_basic_signing_context *data,
252 const uchar *buf, uint32 seq_number,
253 unsigned char calc_md5_mac[16])
255 const size_t offset_end_of_sig = (smb_ss_field + 8);
256 unsigned char sequence_buf[8];
257 struct MD5Context md5_ctx;
258 #if 0
259 /* JRA - apparently this is incorrect. */
260 unsigned char key_buf[16];
261 #endif
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
276 incoming packet.
278 This makes for a bit of fussing about, but it's not too bad.
280 MD5Init(&md5_ctx);
282 /* intialise with the key */
283 MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length);
284 #if 0
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);
293 #endif
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;
318 uint32 send_seq_num;
320 if (!si->doing_signing)
321 return;
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",
326 smb_len(outbuf) ));
327 abort();
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;
335 else
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)
349 return;
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)
363 BOOL good;
364 uint32 reply_seq_number;
365 uint32 saved_seq;
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)
372 return True;
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)));
376 return False;
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) ));
385 return False;
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);
394 if (!good) {
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);
400 #if 1 /* JRATEST */
402 int i;
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 ));
409 break;
413 #endif /* JRATEST */
415 } else {
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 = data->outstanding_packet_list;
431 while (list) {
432 struct outstanding_packet_lookup *old_head = list;
433 DLIST_REMOVE(list, list);
434 SAFE_FREE(old_head);
437 data_blob_free(&data->mac_key);
439 if (data->trans_info)
440 SAFE_FREE(data->trans_info);
442 SAFE_FREE(si->signing_context);
444 return;
447 /***********************************************************
448 SMB signing - Simple implementation - setup the MAC key.
449 ************************************************************/
451 BOOL cli_simple_set_signing(struct cli_state *cli,
452 const DATA_BLOB user_session_key,
453 const DATA_BLOB response)
455 struct smb_basic_signing_context *data;
457 if (!user_session_key.length)
458 return False;
460 if (!cli_set_smb_signing_common(cli)) {
461 return False;
464 if (!set_smb_signing_real_common(&cli->sign_info)) {
465 return False;
468 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
469 memset(data, '\0', sizeof(*data));
471 cli->sign_info.signing_context = data;
473 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
475 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
477 DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
478 dump_data(10, (const char *)user_session_key.data, user_session_key.length);
480 if (response.length) {
481 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
482 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
483 dump_data(10, (const char *)response.data, response.length);
484 } else {
485 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
488 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
490 /* Initialise the sequence number */
491 data->send_seq_num = 0;
493 /* Initialise the list of outstanding packets */
494 data->outstanding_packet_list = NULL;
496 cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
497 cli->sign_info.check_incoming_message = client_check_incoming_message;
498 cli->sign_info.free_signing_context = simple_free_signing_context;
500 return True;
503 /***********************************************************
504 Tell client code we are in a multiple trans reply state.
505 We call this after the last outgoing trans2 packet (which
506 has incremented the sequence numbers), so we must save the
507 current mid and sequence number -2.
508 ************************************************************/
510 void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
512 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
513 uint32 reply_seq_num;
515 if (!cli->sign_info.doing_signing || !data)
516 return;
518 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
519 ZERO_STRUCTP(data->trans_info);
521 /* This ensures the sequence is pulled off the outstanding packet list */
522 if (!get_sequence_for_reply(&data->outstanding_packet_list,
523 mid, &reply_seq_num)) {
524 DEBUG(1, ("get_sequence_for_reply failed - did we enter the trans signing state without sending a packet?\n"));
525 return;
528 data->trans_info->send_seq_num = reply_seq_num - 1;
529 data->trans_info->mid = mid;
530 data->trans_info->reply_seq_num = reply_seq_num;
532 DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
533 data->send_seq_num = %u\n",
534 (unsigned int)data->trans_info->mid,
535 (unsigned int)data->trans_info->reply_seq_num,
536 (unsigned int)data->trans_info->send_seq_num,
537 (unsigned int)data->send_seq_num ));
540 /***********************************************************
541 Tell client code we are out of a multiple trans reply state.
542 ************************************************************/
544 void cli_signing_trans_stop(struct cli_state *cli)
546 struct smb_basic_signing_context *data = cli->sign_info.signing_context;
548 if (!cli->sign_info.doing_signing || !data)
549 return;
551 DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
552 data->send_seq_num = %u\n",
553 (unsigned int)data->trans_info->mid,
554 (unsigned int)data->trans_info->reply_seq_num,
555 (unsigned int)data->trans_info->send_seq_num,
556 (unsigned int)data->send_seq_num ));
558 SAFE_FREE(data->trans_info);
559 data->trans_info = NULL;
562 /***********************************************************
563 SMB signing - TEMP implementation - calculate a MAC to send.
564 ************************************************************/
566 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
568 /* mark the packet as signed - BEFORE we sign it...*/
569 mark_packet_signed(outbuf);
571 /* I wonder what BSRSPYL stands for - but this is what MS
572 actually sends! */
573 memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
574 return;
577 /***********************************************************
578 SMB signing - TEMP implementation - check a MAC sent by server.
579 ************************************************************/
581 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
583 return True;
586 /***********************************************************
587 SMB signing - TEMP implementation - free signing context
588 ************************************************************/
590 static void temp_free_signing_context(struct smb_sign_info *si)
592 return;
595 /***********************************************************
596 SMB signing - NULL implementation - setup the MAC key.
597 ************************************************************/
599 BOOL cli_null_set_signing(struct cli_state *cli)
601 return null_set_signing(&cli->sign_info);
604 /***********************************************************
605 SMB signing - temp implementation - setup the MAC key.
606 ************************************************************/
608 BOOL cli_temp_set_signing(struct cli_state *cli)
610 if (!cli_set_smb_signing_common(cli)) {
611 return False;
614 cli->sign_info.signing_context = NULL;
616 cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
617 cli->sign_info.check_incoming_message = temp_check_incoming_message;
618 cli->sign_info.free_signing_context = temp_free_signing_context;
620 return True;
623 void cli_free_signing_context(struct cli_state *cli)
625 free_signing_context(&cli->sign_info);
629 * Sign a packet with the current mechanism
632 void cli_calculate_sign_mac(struct cli_state *cli)
634 cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
638 * Check a packet with the current mechanism
639 * @return False if we had an established signing connection
640 * which had a bad checksum, True otherwise.
643 BOOL cli_check_sign_mac(struct cli_state *cli)
645 if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
646 free_signing_context(&cli->sign_info);
647 return False;
649 return True;
652 /***********************************************************
653 SMB signing - Server implementation - send the MAC.
654 ************************************************************/
656 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
658 unsigned char calc_md5_mac[16];
659 struct smb_basic_signing_context *data = si->signing_context;
660 uint32 send_seq_number = data->send_seq_num;
661 BOOL was_deferred_packet = False;
662 uint16 mid;
664 if (!si->doing_signing) {
665 return;
668 /* JRA Paranioa test - we should be able to get rid of this... */
669 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
670 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
671 smb_len(outbuf) ));
672 abort();
675 /* mark the packet as signed - BEFORE we sign it...*/
676 mark_packet_signed(outbuf);
678 mid = SVAL(outbuf, smb_mid);
680 /* See if this is a reply for a deferred packet. */
681 was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
683 if (data->trans_info && (data->trans_info->mid == mid)) {
684 /* This is a reply in a trans stream. Use the sequence
685 * number associated with the stream mid. */
686 send_seq_number = data->trans_info->send_seq_num;
689 simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
691 DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
692 dump_data(10, (const char *)calc_md5_mac, 8);
694 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
696 /* cli->outbuf[smb_ss_field+2]=0;
697 Uncomment this to test if the remote client actually verifies signatures...*/
699 /* Don't mess with the sequence number for a deferred packet. */
700 if (was_deferred_packet) {
701 return;
704 if (!data->trans_info) {
705 /* Always increment if not in a trans stream. */
706 data->send_seq_num++;
707 } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
708 /* Increment if this is the first reply in a trans stream or a
709 * packet that doesn't belong to this stream (different mid). */
710 data->send_seq_num++;
714 /***********************************************************
715 Is an incoming packet an oplock break reply ?
716 ************************************************************/
718 static BOOL is_oplock_break(char *inbuf)
720 if (CVAL(inbuf,smb_com) != SMBlockingX)
721 return False;
723 if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
724 return False;
726 DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
727 return True;
730 /***********************************************************
731 SMB signing - Server implementation - check a MAC sent by server.
732 ************************************************************/
734 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
736 BOOL good;
737 struct smb_basic_signing_context *data = si->signing_context;
738 uint32 reply_seq_number = data->send_seq_num;
739 uint32 saved_seq;
740 unsigned char calc_md5_mac[16];
741 unsigned char *server_sent_mac;
742 uint mid;
744 if (!si->doing_signing)
745 return True;
747 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
748 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
749 return False;
752 mid = SVAL(inbuf, smb_mid);
754 /* Is this part of a trans stream ? */
755 if (data->trans_info && (data->trans_info->mid == mid)) {
756 /* If so we don't increment the sequence. */
757 reply_seq_number = data->trans_info->reply_seq_num;
758 } else {
759 /* We always increment the sequence number. */
760 data->send_seq_num++;
762 /* If we get an asynchronous oplock break reply and there
763 * isn't a reply pending we need to re-sync the sequence
764 * number.
766 if (is_oplock_break(inbuf)) {
767 DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
768 data->send_seq_num++;
772 saved_seq = reply_seq_number;
773 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
775 server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
776 good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
778 if (!good) {
780 if (saved_seq) {
781 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
782 (unsigned int)saved_seq));
783 dump_data(5, (const char *)calc_md5_mac, 8);
785 DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
786 (unsigned int)reply_seq_number));
787 dump_data(5, (const char *)server_sent_mac, 8);
790 #if 1 /* JRATEST */
792 int i;
793 reply_seq_number -= 5;
794 for (i = 0; i < 10; i++, reply_seq_number++) {
795 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
796 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
797 DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
798 We were expecting seq %u\n", reply_seq_number, saved_seq ));
799 break;
803 #endif /* JRATEST */
805 } else {
806 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));
807 dump_data(10, (const char *)server_sent_mac, 8);
810 return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
813 /***********************************************************
814 SMB signing - server API's.
815 ************************************************************/
817 static struct smb_sign_info srv_sign_info = {
818 null_sign_outgoing_message,
819 null_check_incoming_message,
820 null_free_signing_context,
821 NULL,
822 False,
823 False,
824 False,
825 False
828 /***********************************************************
829 Turn signing off or on for oplock break code.
830 ************************************************************/
832 BOOL srv_oplock_set_signing(BOOL onoff)
834 BOOL ret = srv_sign_info.doing_signing;
835 srv_sign_info.doing_signing = onoff;
836 return ret;
839 /***********************************************************
840 Called to validate an incoming packet from the client.
841 ************************************************************/
843 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
845 /* Check if it's a session keepalive. */
846 if(CVAL(inbuf,0) == SMBkeepalive)
847 return True;
849 return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
852 /***********************************************************
853 Called to sign an outgoing packet to the client.
854 ************************************************************/
856 void srv_calculate_sign_mac(char *outbuf)
858 /* Check if it's a session keepalive. */
859 /* JRA Paranioa test - do we ever generate these in the server ? */
860 if(CVAL(outbuf,0) == SMBkeepalive)
861 return;
863 srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
866 /***********************************************************
867 Called by server to defer an outgoing packet.
868 ************************************************************/
870 void srv_defer_sign_response(uint16 mid)
872 struct smb_basic_signing_context *data;
874 if (!srv_sign_info.doing_signing)
875 return;
877 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
879 if (!data)
880 return;
883 * Ensure we only store this mid reply once...
886 if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
887 data->send_seq_num++;
891 /***********************************************************
892 Called to remove sequence records when a deferred packet is
893 cancelled by mid. This should never find one....
894 ************************************************************/
896 void srv_cancel_sign_response(uint16 mid)
898 struct smb_basic_signing_context *data;
899 uint32 dummy_seq;
901 if (!srv_sign_info.doing_signing)
902 return;
904 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
906 if (!data)
907 return;
909 DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
911 while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
915 /***********************************************************
916 Called by server negprot when signing has been negotiated.
917 ************************************************************/
919 void srv_set_signing_negotiated(void)
921 srv_sign_info.allow_smb_signing = True;
922 srv_sign_info.negotiated_smb_signing = True;
923 if (lp_server_signing() == Required)
924 srv_sign_info.mandatory_signing = True;
926 srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
927 srv_sign_info.check_incoming_message = temp_check_incoming_message;
928 srv_sign_info.free_signing_context = temp_free_signing_context;
931 /***********************************************************
932 Returns whether signing is active. We can't use sendfile or raw
933 reads/writes if it is.
934 ************************************************************/
936 BOOL srv_is_signing_active(void)
938 return srv_sign_info.doing_signing;
942 /***********************************************************
943 Returns whether signing is negotiated. We can't use it unless it was
944 in the negprot.
945 ************************************************************/
947 BOOL srv_is_signing_negotiated(void)
949 return srv_sign_info.negotiated_smb_signing;
952 /***********************************************************
953 Returns whether signing is actually happening
954 ************************************************************/
956 BOOL srv_signing_started(void)
958 struct smb_basic_signing_context *data;
960 if (!srv_sign_info.doing_signing) {
961 return False;
964 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
965 if (!data)
966 return False;
968 if (data->send_seq_num == 0) {
969 return False;
972 return True;
976 /***********************************************************
977 Tell server code we are in a multiple trans reply state.
978 ************************************************************/
980 void srv_signing_trans_start(uint16 mid)
982 struct smb_basic_signing_context *data;
984 if (!srv_sign_info.doing_signing)
985 return;
987 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
988 if (!data)
989 return;
991 data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
992 ZERO_STRUCTP(data->trans_info);
994 data->trans_info->reply_seq_num = data->send_seq_num-1;
995 data->trans_info->mid = mid;
996 data->trans_info->send_seq_num = data->send_seq_num;
998 DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
999 data->send_seq_num = %u\n",
1000 (unsigned int)mid,
1001 (unsigned int)data->trans_info->reply_seq_num,
1002 (unsigned int)data->trans_info->send_seq_num,
1003 (unsigned int)data->send_seq_num ));
1006 /***********************************************************
1007 Tell server code we are out of a multiple trans reply state.
1008 ************************************************************/
1010 void srv_signing_trans_stop(void)
1012 struct smb_basic_signing_context *data;
1014 if (!srv_sign_info.doing_signing)
1015 return;
1017 data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1018 if (!data || !data->trans_info)
1019 return;
1021 DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1022 data->send_seq_num = %u\n",
1023 (unsigned int)data->trans_info->mid,
1024 (unsigned int)data->trans_info->reply_seq_num,
1025 (unsigned int)data->trans_info->send_seq_num,
1026 (unsigned int)data->send_seq_num ));
1028 SAFE_FREE(data->trans_info);
1029 data->trans_info = NULL;
1032 /***********************************************************
1033 Turn on signing from this packet onwards.
1034 ************************************************************/
1036 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1038 struct smb_basic_signing_context *data;
1040 if (!user_session_key.length)
1041 return;
1043 if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
1044 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
1045 (unsigned int)srv_sign_info.negotiated_smb_signing,
1046 (unsigned int)srv_sign_info.mandatory_signing ));
1047 return;
1050 /* Once we've turned on, ignore any more sessionsetups. */
1051 if (srv_sign_info.doing_signing) {
1052 return;
1055 if (srv_sign_info.free_signing_context)
1056 srv_sign_info.free_signing_context(&srv_sign_info);
1058 srv_sign_info.doing_signing = True;
1060 data = SMB_XMALLOC_P(struct smb_basic_signing_context);
1061 memset(data, '\0', sizeof(*data));
1063 srv_sign_info.signing_context = data;
1065 data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1067 memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
1068 if (response.length)
1069 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
1071 dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1073 DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
1074 BOOLSTR(srv_sign_info.negotiated_smb_signing),
1075 BOOLSTR(srv_sign_info.mandatory_signing) ));
1077 /* Initialise the sequence number */
1078 data->send_seq_num = 0;
1080 /* Initialise the list of outstanding packets */
1081 data->outstanding_packet_list = NULL;
1083 srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
1084 srv_sign_info.check_incoming_message = srv_check_incoming_message;
1085 srv_sign_info.free_signing_context = simple_free_signing_context;