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
6
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.
11
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.
16
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.
20*/
21
22#include "includes.h"
23
24/* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
25struct outstanding_packet_lookup {
26	uint16 mid;
27	uint32 reply_seq_num;
28	struct outstanding_packet_lookup *prev, *next;
29};
30
31/* Store the data for an ongoing trans/trans2/nttrans operation. */
32struct trans_info_context {
33	uint16 mid;
34	uint32 send_seq_num;
35	uint32 reply_seq_num;
36};
37
38struct 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;
43};
44
45static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list,
46				     uint16 mid, uint32 reply_seq_num)
47{
48	struct outstanding_packet_lookup *t;
49
50	/* Ensure we only add a mid once. */
51	for (t = *list; t; t = t->next) {
52		if (t->mid == mid) {
53			return False;
54		}
55	}
56
57	t = SMB_XMALLOC_P(struct outstanding_packet_lookup);
58	ZERO_STRUCTP(t);
59
60	t->mid = mid;
61	t->reply_seq_num = reply_seq_num;
62
63	/*
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>.
70	 */
71
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;
76}
77
78static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
79				   uint16 mid, uint32 *reply_seq_num)
80{
81	struct outstanding_packet_lookup *t;
82
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;
91		}
92	}
93	return False;
94}
95
96/***********************************************************
97 SMB signing - Common code before we set a new signing implementation
98************************************************************/
99
100static BOOL cli_set_smb_signing_common(struct cli_state *cli)
101{
102	if (!cli->sign_info.negotiated_smb_signing
103	    && !cli->sign_info.mandatory_signing) {
104		return False;
105	}
106
107	if (cli->sign_info.doing_signing) {
108		return False;
109	}
110
111	if (cli->sign_info.free_signing_context)
112		cli->sign_info.free_signing_context(&cli->sign_info);
113
114	/* These calls are INCOMPATIBLE with SMB signing */
115	cli->readbraw_supported = False;
116	cli->writebraw_supported = False;
117
118	return True;
119}
120
121/***********************************************************
122 SMB signing - Common code for 'real' implementations
123************************************************************/
124
125static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
126{
127	if (si->mandatory_signing) {
128		DEBUG(5, ("Mandatory SMB signing enabled!\n"));
129	}
130
131	si->doing_signing = True;
132	DEBUG(5, ("SMB signing enabled!\n"));
133
134	return True;
135}
136
137static void mark_packet_signed(char *outbuf)
138{
139	uint16 flags2;
140	flags2 = SVAL(outbuf,smb_flg2);
141	flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
142	SSVAL(outbuf,smb_flg2, flags2);
143}
144
145/***********************************************************
146 SMB signing - NULL implementation - calculate a MAC to send.
147************************************************************/
148
149static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
150{
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;
155}
156
157/***********************************************************
158 SMB signing - NULL implementation - check a MAC sent by server.
159************************************************************/
160
161static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
162{
163	return True;
164}
165
166/***********************************************************
167 SMB signing - NULL implementation - free signing context
168************************************************************/
169
170static void null_free_signing_context(struct smb_sign_info *si)
171{
172	return;
173}
174
175/**
176 SMB signing - NULL implementation - setup the MAC key.
177
178 @note Used as an initialisation only - it will not correctly
179       shut down a real signing mechanism
180*/
181
182static BOOL null_set_signing(struct smb_sign_info *si)
183{
184	si->signing_context = NULL;
185
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;
189
190	return True;
191}
192
193/**
194 * Free the signing context
195 */
196
197static void free_signing_context(struct smb_sign_info *si)
198{
199	if (si->free_signing_context) {
200		si->free_signing_context(si);
201		si->signing_context = NULL;
202	}
203
204	null_set_signing(si);
205}
206
207
208static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok)
209{
210	if (good) {
211
212		if (!si->doing_signing) {
213			si->doing_signing = True;
214		}
215
216		if (!si->seen_valid) {
217			si->seen_valid = True;
218		}
219
220	} else {
221		if (!si->mandatory_signing && !si->seen_valid) {
222
223			if (!must_be_ok) {
224				return True;
225			}
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;
242		}
243	}
244	return True;
245}
246
247/***********************************************************
248 SMB signing - Simple implementation - calculate a MAC on the packet
249************************************************************/
250
251static void simple_packet_signature(struct smb_basic_signing_context *data,
252				    const uchar *buf, uint32 seq_number,
253				    unsigned char calc_md5_mac[16])
254{
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];
259
260	/*
261	 * Firstly put the sequence number into the first 4 bytes.
262	 * and zero out the next 4 bytes.
263	 *
264	 * We do this here, to avoid modifying the packet.
265	 */
266
267	DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
268
269	SIVAL(sequence_buf, 0, seq_number);
270	SIVAL(sequence_buf, 4, 0);
271
272	/* Calculate the 16 byte MAC - but don't alter the data in the
273	   incoming packet.
274
275	   This makes for a bit of fussing about, but it's not too bad.
276	*/
277	MD5Init(&md5_ctx);
278
279	/* intialise with the key */
280	MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length);
281#if 0
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);
289	}
290#endif
291
292	/* copy in the first bit of the SMB header */
293	MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
294
295	/* copy in the sequence number, instead of the signature */
296	MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
297
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));
301
302	/* calculate the MD5 sig */
303	MD5Final(calc_md5_mac, &md5_ctx);
304}
305
306
307/***********************************************************
308 SMB signing - Client implementation - send the MAC.
309************************************************************/
310
311static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
312{
313	unsigned char calc_md5_mac[16];
314	struct smb_basic_signing_context *data = si->signing_context;
315	uint32 send_seq_num;
316
317	if (!si->doing_signing)
318		return;
319
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",
323					smb_len(outbuf) ));
324		abort();
325	}
326
327	/* mark the packet as signed - BEFORE we sign it...*/
328	mark_packet_signed(outbuf);
329
330	if (data->trans_info)
331		send_seq_num = data->trans_info->send_seq_num;
332	else
333		send_seq_num = data->send_seq_num;
334
335	simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
336
337	DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
338	dump_data(10, (const char *)calc_md5_mac, 8);
339
340	memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
341
342/*	cli->outbuf[smb_ss_field+2]=0;
343	Uncomment this to test if the remote server actually verifies signatures...*/
344
345	if (data->trans_info)
346		return;
347
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++;
352}
353
354/***********************************************************
355 SMB signing - Client implementation - check a MAC sent by server.
356************************************************************/
357
358static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
359{
360	BOOL good;
361	uint32 reply_seq_number;
362	uint32 saved_seq;
363	unsigned char calc_md5_mac[16];
364	unsigned char *server_sent_mac;
365
366	struct smb_basic_signing_context *data = si->signing_context;
367
368	if (!si->doing_signing)
369		return True;
370
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)));
373		return False;
374	}
375
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) ));
382		return False;
383	}
384
385	saved_seq = reply_seq_number;
386	simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
387
388	server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
389	good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
390
391	if (!good) {
392		DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
393		dump_data(5, (const char *)calc_md5_mac, 8);
394
395		DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
396		dump_data(5, (const char *)server_sent_mac, 8);
397#if 1 /* JRATEST */
398		{
399			int i;
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. \
405We were expecting seq %u\n", reply_seq_number, saved_seq ));
406					break;
407				}
408			}
409		}
410#endif /* JRATEST */
411
412	} else {
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);
415	}
416	return signing_good(inbuf, si, good, saved_seq, must_be_ok);
417}
418
419/***********************************************************
420 SMB signing - Simple implementation - free signing context
421************************************************************/
422
423static void simple_free_signing_context(struct smb_sign_info *si)
424{
425	struct smb_basic_signing_context *data = si->signing_context;
426	struct outstanding_packet_lookup *list = data->outstanding_packet_list;
427
428	while (list) {
429		struct outstanding_packet_lookup *old_head = list;
430		DLIST_REMOVE(list, list);
431		SAFE_FREE(old_head);
432	}
433
434	data_blob_free(&data->mac_key);
435
436	if (data->trans_info)
437		SAFE_FREE(data->trans_info);
438
439	SAFE_FREE(si->signing_context);
440
441	return;
442}
443
444/***********************************************************
445 SMB signing - Simple implementation - setup the MAC key.
446************************************************************/
447
448BOOL cli_simple_set_signing(struct cli_state *cli,
449			    const DATA_BLOB user_session_key,
450			    const DATA_BLOB response)
451{
452	struct smb_basic_signing_context *data;
453
454	if (!user_session_key.length)
455		return False;
456
457	if (!cli_set_smb_signing_common(cli)) {
458		return False;
459	}
460
461	if (!set_smb_signing_real_common(&cli->sign_info)) {
462		return False;
463	}
464
465	data = SMB_XMALLOC_P(struct smb_basic_signing_context);
466	memset(data, '\0', sizeof(*data));
467
468	cli->sign_info.signing_context = data;
469
470	data->mac_key = data_blob(NULL, response.length + user_session_key.length);
471
472	memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
473
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);
476
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);
481	} else {
482		DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
483	}
484
485	dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
486
487	/* Initialise the sequence number */
488	data->send_seq_num = 0;
489
490	/* Initialise the list of outstanding packets */
491	data->outstanding_packet_list = NULL;
492
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;
496
497	return True;
498}
499
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************************************************************/
506
507void cli_signing_trans_start(struct cli_state *cli, uint16 mid)
508{
509	struct smb_basic_signing_context *data = cli->sign_info.signing_context;
510	uint32 reply_seq_num;
511
512	if (!cli->sign_info.doing_signing || !data)
513		return;
514
515	data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
516	ZERO_STRUCTP(data->trans_info);
517
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"));
522	    return;
523	}
524
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;
528
529	DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
530data->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 ));
535}
536
537/***********************************************************
538 Tell client code we are out of a multiple trans reply state.
539************************************************************/
540
541void cli_signing_trans_stop(struct cli_state *cli)
542{
543	struct smb_basic_signing_context *data = cli->sign_info.signing_context;
544
545	if (!cli->sign_info.doing_signing || !data)
546		return;
547
548	DEBUG(10,("cli_signing_trans_stop: freeing mid = %u, reply_seq_num = %u, send_seq_num = %u \
549data->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 ));
554
555	SAFE_FREE(data->trans_info);
556	data->trans_info = NULL;
557}
558
559/***********************************************************
560 SMB signing - TEMP implementation - calculate a MAC to send.
561************************************************************/
562
563static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
564{
565	/* mark the packet as signed - BEFORE we sign it...*/
566	mark_packet_signed(outbuf);
567
568	/* I wonder what BSRSPYL stands for - but this is what MS
569	   actually sends! */
570	memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
571	return;
572}
573
574/***********************************************************
575 SMB signing - TEMP implementation - check a MAC sent by server.
576************************************************************/
577
578static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
579{
580	return True;
581}
582
583/***********************************************************
584 SMB signing - TEMP implementation - free signing context
585************************************************************/
586
587static void temp_free_signing_context(struct smb_sign_info *si)
588{
589	return;
590}
591
592/***********************************************************
593 SMB signing - NULL implementation - setup the MAC key.
594************************************************************/
595
596BOOL cli_null_set_signing(struct cli_state *cli)
597{
598	return null_set_signing(&cli->sign_info);
599}
600
601/***********************************************************
602 SMB signing - temp implementation - setup the MAC key.
603************************************************************/
604
605BOOL cli_temp_set_signing(struct cli_state *cli)
606{
607	if (!cli_set_smb_signing_common(cli)) {
608		return False;
609	}
610
611	cli->sign_info.signing_context = NULL;
612
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;
616
617	return True;
618}
619
620void cli_free_signing_context(struct cli_state *cli)
621{
622	free_signing_context(&cli->sign_info);
623}
624
625/**
626 * Sign a packet with the current mechanism
627 */
628
629void cli_calculate_sign_mac(struct cli_state *cli)
630{
631	cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
632}
633
634/**
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.
638 */
639
640BOOL cli_check_sign_mac(struct cli_state *cli)
641{
642	if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
643		free_signing_context(&cli->sign_info);
644		return False;
645	}
646	return True;
647}
648
649/***********************************************************
650 SMB signing - Server implementation - send the MAC.
651************************************************************/
652
653static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
654{
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;
659	uint16 mid;
660
661	if (!si->doing_signing) {
662		return;
663	}
664
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",
668					smb_len(outbuf) ));
669		abort();
670	}
671
672	/* mark the packet as signed - BEFORE we sign it...*/
673	mark_packet_signed(outbuf);
674
675	mid = SVAL(outbuf, smb_mid);
676
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);
679
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;
684	}
685
686	simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
687
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);
690
691	memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
692
693/*	cli->outbuf[smb_ss_field+2]=0;
694	Uncomment this to test if the remote client actually verifies signatures...*/
695
696	/* Don't mess with the sequence number for a deferred packet. */
697	if (was_deferred_packet) {
698		return;
699	}
700
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++;
708	}
709}
710
711/***********************************************************
712 Is an incoming packet an oplock break reply ?
713************************************************************/
714
715static BOOL is_oplock_break(char *inbuf)
716{
717	if (CVAL(inbuf,smb_com) != SMBlockingX)
718		return False;
719
720	if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
721		return False;
722
723	DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
724	return True;
725}
726
727/***********************************************************
728 SMB signing - Server implementation - check a MAC sent by server.
729************************************************************/
730
731static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
732{
733	BOOL good;
734	struct smb_basic_signing_context *data = si->signing_context;
735	uint32 reply_seq_number = data->send_seq_num;
736	uint32 saved_seq;
737	unsigned char calc_md5_mac[16];
738	unsigned char *server_sent_mac;
739	uint mid;
740
741	if (!si->doing_signing)
742		return True;
743
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)));
746		return False;
747	}
748
749	mid = SVAL(inbuf, smb_mid);
750
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;
755	} else {
756		/* We always increment the sequence number. */
757		data->send_seq_num++;
758
759		/* If we get an asynchronous oplock break reply and there
760		 * isn't a reply pending we need to re-sync the sequence
761		 * number.
762		 */
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++;
766		}
767	}
768
769	saved_seq = reply_seq_number;
770	simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
771
772	server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
773	good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
774
775	if (!good) {
776
777		if (saved_seq) {
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);
781
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);
785		}
786
787#if 1 /* JRATEST */
788		{
789			int i;
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. \
795We were expecting seq %u\n", reply_seq_number, saved_seq ));
796					break;
797				}
798			}
799		}
800#endif /* JRATEST */
801
802	} else {
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);
805	}
806
807	return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
808}
809
810/***********************************************************
811 SMB signing - server API's.
812************************************************************/
813
814static struct smb_sign_info srv_sign_info = {
815	null_sign_outgoing_message,
816	null_check_incoming_message,
817	null_free_signing_context,
818	NULL,
819	False,
820	False,
821	False,
822	False
823};
824
825/***********************************************************
826 Turn signing off or on for oplock break code.
827************************************************************/
828
829BOOL srv_oplock_set_signing(BOOL onoff)
830{
831	BOOL ret = srv_sign_info.doing_signing;
832	srv_sign_info.doing_signing = onoff;
833	return ret;
834}
835
836/***********************************************************
837 Called to validate an incoming packet from the client.
838************************************************************/
839
840BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
841{
842	/* Check if it's a session keepalive. */
843	if(CVAL(inbuf,0) == SMBkeepalive)
844		return True;
845
846	return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
847}
848
849/***********************************************************
850 Called to sign an outgoing packet to the client.
851************************************************************/
852
853void srv_calculate_sign_mac(char *outbuf)
854{
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)
858		return;
859
860	srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
861}
862
863/***********************************************************
864 Called by server to defer an outgoing packet.
865************************************************************/
866
867void srv_defer_sign_response(uint16 mid)
868{
869	struct smb_basic_signing_context *data;
870
871	if (!srv_sign_info.doing_signing)
872		return;
873
874	data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
875
876	if (!data)
877		return;
878
879	/*
880	 * Ensure we only store this mid reply once...
881	 */
882
883	if (store_sequence_for_reply(&data->outstanding_packet_list, mid, data->send_seq_num)) {
884		data->send_seq_num++;
885	}
886}
887
888/***********************************************************
889 Called to remove sequence records when a deferred packet is
890 cancelled by mid. This should never find one....
891************************************************************/
892
893void srv_cancel_sign_response(uint16 mid)
894{
895	struct smb_basic_signing_context *data;
896	uint32 dummy_seq;
897
898	if (!srv_sign_info.doing_signing)
899		return;
900
901	data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
902
903	if (!data)
904		return;
905
906	DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
907
908	while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
909		;
910}
911
912/***********************************************************
913 Called by server negprot when signing has been negotiated.
914************************************************************/
915
916void srv_set_signing_negotiated(void)
917{
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;
922
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;
926}
927
928/***********************************************************
929 Returns whether signing is active. We can't use sendfile or raw
930 reads/writes if it is.
931************************************************************/
932
933BOOL srv_is_signing_active(void)
934{
935	return srv_sign_info.doing_signing;
936}
937
938
939/***********************************************************
940 Returns whether signing is negotiated. We can't use it unless it was
941 in the negprot.
942************************************************************/
943
944BOOL srv_is_signing_negotiated(void)
945{
946	return srv_sign_info.negotiated_smb_signing;
947}
948
949/***********************************************************
950 Returns whether signing is actually happening
951************************************************************/
952
953BOOL srv_signing_started(void)
954{
955	struct smb_basic_signing_context *data;
956
957	if (!srv_sign_info.doing_signing) {
958		return False;
959	}
960
961	data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
962	if (!data)
963		return False;
964
965	if (data->send_seq_num == 0) {
966		return False;
967	}
968
969	return True;
970}
971
972
973/***********************************************************
974 Tell server code we are in a multiple trans reply state.
975************************************************************/
976
977void srv_signing_trans_start(uint16 mid)
978{
979	struct smb_basic_signing_context *data;
980
981	if (!srv_sign_info.doing_signing)
982		return;
983
984	data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
985	if (!data)
986		return;
987
988	data->trans_info = SMB_XMALLOC_P(struct trans_info_context);
989	ZERO_STRUCTP(data->trans_info);
990
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;
994
995	DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
996data->send_seq_num = %u\n",
997			(unsigned int)mid,
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 ));
1001}
1002
1003/***********************************************************
1004 Tell server code we are out of a multiple trans reply state.
1005************************************************************/
1006
1007void srv_signing_trans_stop(void)
1008{
1009	struct smb_basic_signing_context *data;
1010
1011	if (!srv_sign_info.doing_signing)
1012		return;
1013
1014	data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
1015	if (!data || !data->trans_info)
1016		return;
1017
1018	DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
1019data->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 ));
1024
1025	SAFE_FREE(data->trans_info);
1026	data->trans_info = NULL;
1027}
1028
1029/***********************************************************
1030 Turn on signing from this packet onwards.
1031************************************************************/
1032
1033void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
1034{
1035	struct smb_basic_signing_context *data;
1036
1037	if (!user_session_key.length)
1038		return;
1039
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 ));
1044		return;
1045	}
1046
1047	/* Once we've turned on, ignore any more sessionsetups. */
1048	if (srv_sign_info.doing_signing) {
1049		return;
1050	}
1051
1052	if (srv_sign_info.free_signing_context)
1053		srv_sign_info.free_signing_context(&srv_sign_info);
1054
1055	srv_sign_info.doing_signing = True;
1056
1057	data = SMB_XMALLOC_P(struct smb_basic_signing_context);
1058	memset(data, '\0', sizeof(*data));
1059
1060	srv_sign_info.signing_context = data;
1061
1062	data->mac_key = data_blob(NULL, response.length + user_session_key.length);
1063
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);
1067
1068	dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
1069
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) ));
1073
1074	/* Initialise the sequence number */
1075	data->send_seq_num = 0;
1076
1077	/* Initialise the list of outstanding packets */
1078	data->outstanding_packet_list = NULL;
1079
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;
1083}
1084