500ff7cc6e2113e7d43e97a0f432132044711d3a
[samba.git] / source / libsmb / smb_signing.c
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 */
25 struct 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. */
32 struct trans_info_context {
33         uint16 mid;
34         uint32 send_seq_num;
35         uint32 reply_seq_num;
36 };
37
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;
43 };
44
45 static 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
78 static 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
100 static 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
125 static 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
137 static 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
149 static 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
161 static 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
170 static 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
182 static 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  
197 static 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
208 static 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
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])
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
311 static 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
358 static 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. \
405 We 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
423 static 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
448 BOOL 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
507 void 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 \
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 ));
535 }
536
537 /***********************************************************
538  Tell client code we are out of a multiple trans reply state.
539 ************************************************************/
540
541 void 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 \
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 ));
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
563 static 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
578 static 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
587 static 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
596 BOOL 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
605 BOOL 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
620 void 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  
629 void 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  
640 BOOL 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
653 static 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
715 static 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
731 static 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. \
795 We 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
814 static 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
829 BOOL 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
840 BOOL 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
853 void 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
867 void 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
893 void 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
916 void 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
933 BOOL 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
944 BOOL 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
953 BOOL 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
977 void 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 \
996 data->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
1007 void 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 \
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 ));
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
1033 void 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 }