(merge from 3.0)
[nivanova/samba-autobuild/.git] / source3 / 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 void store_sequence_for_reply(struct outstanding_packet_lookup **list, 
46                                      uint16 mid, uint32 reply_seq_num)
47 {
48         struct outstanding_packet_lookup *t;
49         struct outstanding_packet_lookup *tmp;
50         
51         t = smb_xmalloc(sizeof(*t));
52         ZERO_STRUCTP(t);
53
54         DLIST_ADD_END(*list, t, tmp);
55         t->mid = mid;
56         t->reply_seq_num = reply_seq_num;
57
58         DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
59                         (unsigned int)reply_seq_num, (unsigned int)mid ));
60 }
61
62 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
63                                    uint16 mid, uint32 *reply_seq_num)
64 {
65         struct outstanding_packet_lookup *t;
66
67         for (t = *list; t; t = t->next) {
68                 if (t->mid == mid) {
69                         *reply_seq_num = t->reply_seq_num;
70                         DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
71                                 (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
72                         DLIST_REMOVE(*list, t);
73                         SAFE_FREE(t);
74                         return True;
75                 }
76         }
77         return False;
78 }
79
80 /***********************************************************
81  SMB signing - Common code before we set a new signing implementation
82 ************************************************************/
83
84 static BOOL cli_set_smb_signing_common(struct cli_state *cli) 
85 {
86         if (!cli->sign_info.negotiated_smb_signing 
87             && !cli->sign_info.mandatory_signing) {
88                 return False;
89         }
90
91         if (cli->sign_info.doing_signing) {
92                 return False;
93         }
94         
95         if (cli->sign_info.free_signing_context)
96                 cli->sign_info.free_signing_context(&cli->sign_info);
97
98         /* These calls are INCOMPATIBLE with SMB signing */
99         cli->readbraw_supported = False;
100         cli->writebraw_supported = False;
101         
102         return True;
103 }
104
105 /***********************************************************
106  SMB signing - Common code for 'real' implementations
107 ************************************************************/
108
109 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
110 {
111         if (si->mandatory_signing) {
112                 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
113         }
114
115         si->doing_signing = True;
116         DEBUG(5, ("SMB signing enabled!\n"));
117
118         return True;
119 }
120
121 static void mark_packet_signed(char *outbuf)
122 {
123         uint16 flags2;
124         flags2 = SVAL(outbuf,smb_flg2);
125         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
126         SSVAL(outbuf,smb_flg2, flags2);
127 }
128
129 /***********************************************************
130  SMB signing - NULL implementation - calculate a MAC to send.
131 ************************************************************/
132
133 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
134 {
135         /* we can't zero out the sig, as we might be trying to send a
136            session request - which is NBT-level, not SMB level and doesn't
137            have the field */
138         return;
139 }
140
141 /***********************************************************
142  SMB signing - NULL implementation - check a MAC sent by server.
143 ************************************************************/
144
145 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
146 {
147         return True;
148 }
149
150 /***********************************************************
151  SMB signing - NULL implementation - free signing context
152 ************************************************************/
153
154 static void null_free_signing_context(struct smb_sign_info *si)
155 {
156         return;
157 }
158
159 /**
160  SMB signing - NULL implementation - setup the MAC key.
161
162  @note Used as an initialisation only - it will not correctly
163        shut down a real signing mechanism
164 */
165
166 static BOOL null_set_signing(struct smb_sign_info *si)
167 {
168         si->signing_context = NULL;
169         
170         si->sign_outgoing_message = null_sign_outgoing_message;
171         si->check_incoming_message = null_check_incoming_message;
172         si->free_signing_context = null_free_signing_context;
173
174         return True;
175 }
176
177 /**
178  * Free the signing context
179  */
180  
181 static void free_signing_context(struct smb_sign_info *si)
182 {
183         if (si->free_signing_context) {
184                 si->free_signing_context(si);
185                 si->signing_context = NULL;
186         }
187
188         null_set_signing(si);
189 }
190
191
192 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq) 
193 {
194         if (good && !si->doing_signing) {
195                 si->doing_signing = True;
196         }
197
198         if (!good) {
199                 if (si->doing_signing) {
200                         struct smb_basic_signing_context *data = si->signing_context;
201
202                         /* W2K sends a bad first signature but the sign engine is on.... JRA. */
203                         if (data->send_seq_num > 1)
204                                 DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n",
205                                                         (unsigned int)seq ));
206
207                         return False;
208                 } else {
209                         DEBUG(3, ("signing_good: Peer did not sign reply correctly\n"));
210                         free_signing_context(si);
211                         return False;
212                 }
213         }
214         return True;
215 }       
216
217 /***********************************************************
218  SMB signing - Simple implementation - calculate a MAC on the packet
219 ************************************************************/
220
221 static void simple_packet_signature(struct smb_basic_signing_context *data, 
222                                     const uchar *buf, uint32 seq_number, 
223                                     unsigned char calc_md5_mac[16])
224 {
225         const size_t offset_end_of_sig = (smb_ss_field + 8);
226         unsigned char sequence_buf[8];
227         struct MD5Context md5_ctx;
228
229         /*
230          * Firstly put the sequence number into the first 4 bytes.
231          * and zero out the next 4 bytes.
232          *
233          * We do this here, to avoid modifying the packet.
234          */
235
236         DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
237
238         SIVAL(sequence_buf, 0, seq_number);
239         SIVAL(sequence_buf, 4, 0);
240
241         /* Calculate the 16 byte MAC - but don't alter the data in the
242            incoming packet.
243            
244            This makes for a bit of fussing about, but it's not too bad.
245         */
246         MD5Init(&md5_ctx);
247
248         /* intialise with the key */
249         MD5Update(&md5_ctx, data->mac_key.data, 
250                   data->mac_key.length); 
251
252         /* copy in the first bit of the SMB header */
253         MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
254
255         /* copy in the sequence number, instead of the signature */
256         MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
257
258         /* copy in the rest of the packet in, skipping the signature */
259         MD5Update(&md5_ctx, buf + offset_end_of_sig, 
260                   smb_len(buf) - (offset_end_of_sig - 4));
261
262         /* calculate the MD5 sig */ 
263         MD5Final(calc_md5_mac, &md5_ctx);
264 }
265
266
267 /***********************************************************
268  SMB signing - Client implementation - send the MAC.
269 ************************************************************/
270
271 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
272 {
273         unsigned char calc_md5_mac[16];
274         struct smb_basic_signing_context *data = si->signing_context;
275         uint32 send_seq_num;
276
277         if (!si->doing_signing)
278                 return;
279
280         /* JRA Paranioa test - we should be able to get rid of this... */
281         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
282                 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
283                                         smb_len(outbuf) ));
284                 abort();
285         }
286
287         /* mark the packet as signed - BEFORE we sign it...*/
288         mark_packet_signed(outbuf);
289
290         if (data->trans_info)
291                 send_seq_num = data->trans_info->send_seq_num;
292         else
293                 send_seq_num = data->send_seq_num;
294
295         simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac);
296
297         DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
298         dump_data(10, (const char *)calc_md5_mac, 8);
299
300         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
301
302 /*      cli->outbuf[smb_ss_field+2]=0; 
303         Uncomment this to test if the remote server actually verifies signatures...*/
304
305         if (data->trans_info)
306                 return;
307
308         data->send_seq_num++;
309         store_sequence_for_reply(&data->outstanding_packet_list, 
310                                  SVAL(outbuf,smb_mid), data->send_seq_num);
311         data->send_seq_num++;
312 }
313
314 /***********************************************************
315  SMB signing - Client implementation - check a MAC sent by server.
316 ************************************************************/
317
318 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
319 {
320         BOOL good;
321         uint32 reply_seq_number;
322         uint32 saved_seq;
323         unsigned char calc_md5_mac[16];
324         unsigned char *server_sent_mac;
325
326         struct smb_basic_signing_context *data = si->signing_context;
327
328         if (!si->doing_signing)
329                 return True;
330
331         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
332                 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
333                 return False;
334         }
335
336         if (data->trans_info) {
337                 reply_seq_number = data->trans_info->reply_seq_num;
338         } else if (!get_sequence_for_reply(&data->outstanding_packet_list, 
339                                     SVAL(inbuf, smb_mid), &reply_seq_number)) {
340                 DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n",
341                                         (unsigned int) SVAL(inbuf, smb_mid) ));
342                 return False;
343         }
344
345         saved_seq = reply_seq_number;
346         simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
347
348         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
349         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
350         
351         if (!good) {
352                 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
353                 dump_data(5, (const char *)calc_md5_mac, 8);
354                 
355                 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
356                 dump_data(5, (const char *)server_sent_mac, 8);
357 #if 1 /* JRATEST */
358                 {
359                         int i;
360                         reply_seq_number -= 5;
361                         for (i = 0; i < 10; i++, reply_seq_number++) {
362                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
363                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
364                                         DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
365 We were expecting seq %u\n", reply_seq_number, saved_seq ));
366                                         break;
367                                 }
368                         }
369                 }
370 #endif /* JRATEST */
371
372         } else {
373                 DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
374                 dump_data(10, (const char *)server_sent_mac, 8);
375         }
376         return signing_good(inbuf, si, good, saved_seq);
377 }
378
379 /***********************************************************
380  SMB signing - Simple implementation - free signing context
381 ************************************************************/
382
383 static void simple_free_signing_context(struct smb_sign_info *si)
384 {
385         struct smb_basic_signing_context *data = si->signing_context;
386         struct outstanding_packet_lookup *list = data->outstanding_packet_list;
387         
388         while (list) {
389                 struct outstanding_packet_lookup *old_head = list;
390                 DLIST_REMOVE(list, list);
391                 SAFE_FREE(old_head);
392         }
393
394         data_blob_free(&data->mac_key);
395
396         if (data->trans_info)
397                 SAFE_FREE(data->trans_info);
398
399         SAFE_FREE(si->signing_context);
400
401         return;
402 }
403
404 /***********************************************************
405  SMB signing - Simple implementation - setup the MAC key.
406 ************************************************************/
407
408 BOOL cli_simple_set_signing(struct cli_state *cli, const DATA_BLOB user_session_key, const DATA_BLOB response)
409 {
410         struct smb_basic_signing_context *data;
411
412         if (!user_session_key.length)
413                 return False;
414
415         if (!cli_set_smb_signing_common(cli)) {
416                 return False;
417         }
418
419         if (!set_smb_signing_real_common(&cli->sign_info)) {
420                 return False;
421         }
422
423         data = smb_xmalloc(sizeof(*data));
424         memset(data, '\0', sizeof(*data));
425
426         cli->sign_info.signing_context = data;
427         
428         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
429
430         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
431
432         DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
433         dump_data(10, (const char *)user_session_key.data, user_session_key.length);
434
435         if (response.length) {
436                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
437                 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
438                 dump_data(10, (const char *)response.data, response.length);
439         } else {
440                 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
441         }
442
443         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
444
445         /* Initialise the sequence number */
446         data->send_seq_num = 0;
447
448         /* Initialise the list of outstanding packets */
449         data->outstanding_packet_list = NULL;
450
451         cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
452         cli->sign_info.check_incoming_message = client_check_incoming_message;
453         cli->sign_info.free_signing_context = simple_free_signing_context;
454
455         return True;
456 }
457
458 /***********************************************************
459  Tell client code we are in a multiple trans reply state.
460 ************************************************************/
461
462 void cli_signing_trans_start(struct cli_state *cli)
463 {
464         struct smb_basic_signing_context *data = cli->sign_info.signing_context;
465
466         if (!cli->sign_info.doing_signing || !data)
467                 return;
468
469         data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
470         ZERO_STRUCTP(data->trans_info);
471
472         data->trans_info->send_seq_num = data->send_seq_num;
473         data->trans_info->mid = SVAL(cli->outbuf,smb_mid);
474         data->trans_info->reply_seq_num = data->send_seq_num+1;
475
476         DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
477 data->send_seq_num = %u\n",
478                         (unsigned int)data->trans_info->mid,
479                         (unsigned int)data->trans_info->reply_seq_num,
480                         (unsigned int)data->trans_info->send_seq_num,
481                         (unsigned int)data->send_seq_num ));
482 }
483
484 /***********************************************************
485  Tell client code we are out of a multiple trans reply state.
486 ************************************************************/
487
488 void cli_signing_trans_stop(struct cli_state *cli)
489 {
490         struct smb_basic_signing_context *data = cli->sign_info.signing_context;
491
492         if (!cli->sign_info.doing_signing || !data)
493                 return;
494
495         SAFE_FREE(data->trans_info);
496         data->trans_info = NULL;
497
498         data->send_seq_num += 2;
499 }
500
501 /***********************************************************
502  SMB signing - TEMP implementation - calculate a MAC to send.
503 ************************************************************/
504
505 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
506 {
507         /* mark the packet as signed - BEFORE we sign it...*/
508         mark_packet_signed(outbuf);
509
510         /* I wonder what BSRSPYL stands for - but this is what MS 
511            actually sends! */
512         memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
513         return;
514 }
515
516 /***********************************************************
517  SMB signing - TEMP implementation - check a MAC sent by server.
518 ************************************************************/
519
520 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
521 {
522         return True;
523 }
524
525 /***********************************************************
526  SMB signing - TEMP implementation - free signing context
527 ************************************************************/
528
529 static void temp_free_signing_context(struct smb_sign_info *si)
530 {
531         return;
532 }
533
534 /***********************************************************
535  SMB signing - NULL implementation - setup the MAC key.
536 ************************************************************/
537
538 BOOL cli_null_set_signing(struct cli_state *cli)
539 {
540         return null_set_signing(&cli->sign_info);
541 }
542
543 /***********************************************************
544  SMB signing - temp implementation - setup the MAC key.
545 ************************************************************/
546
547 BOOL cli_temp_set_signing(struct cli_state *cli)
548 {
549         if (!cli_set_smb_signing_common(cli)) {
550                 return False;
551         }
552
553         cli->sign_info.signing_context = NULL;
554         
555         cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
556         cli->sign_info.check_incoming_message = temp_check_incoming_message;
557         cli->sign_info.free_signing_context = temp_free_signing_context;
558
559         return True;
560 }
561
562 void cli_free_signing_context(struct cli_state *cli)
563 {
564         free_signing_context(&cli->sign_info);
565 }
566
567 /**
568  * Sign a packet with the current mechanism
569  */
570  
571 void cli_calculate_sign_mac(struct cli_state *cli)
572 {
573         cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
574 }
575
576 /**
577  * Check a packet with the current mechanism
578  * @return False if we had an established signing connection
579  *         which had a bad checksum, True otherwise.
580  */
581  
582 BOOL cli_check_sign_mac(struct cli_state *cli) 
583 {
584         if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) {
585                 free_signing_context(&cli->sign_info);  
586                 return False;
587         }
588         return True;
589 }
590
591 /***********************************************************
592  SMB signing - Server implementation - send the MAC.
593 ************************************************************/
594
595 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
596 {
597         unsigned char calc_md5_mac[16];
598         struct smb_basic_signing_context *data = si->signing_context;
599         uint32 send_seq_number = data->send_seq_num;
600         BOOL was_deferred_packet = False;
601         uint16 mid;
602
603         if (!si->doing_signing) {
604                 return;
605         }
606
607         /* JRA Paranioa test - we should be able to get rid of this... */
608         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
609                 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
610                                         smb_len(outbuf) ));
611                 abort();
612         }
613
614         /* mark the packet as signed - BEFORE we sign it...*/
615         mark_packet_signed(outbuf);
616
617         mid = SVAL(outbuf, smb_mid);
618
619         /* See if this is a reply for a deferred packet. */
620         was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
621
622         if (data->trans_info && (data->trans_info->mid == mid)) {
623                 /* This is a reply in a trans stream. Use the sequence
624                  * number associated with the stream mid. */
625                 send_seq_number = data->trans_info->send_seq_num;
626         }
627
628         simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
629
630         DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
631         dump_data(10, (const char *)calc_md5_mac, 8);
632
633         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
634
635 /*      cli->outbuf[smb_ss_field+2]=0; 
636         Uncomment this to test if the remote client actually verifies signatures...*/
637
638         /* Don't mess with the sequence number for a deferred packet. */
639         if (was_deferred_packet) {
640                 return;
641         }
642
643         if (!data->trans_info) {
644                 /* Always increment if not in a trans stream. */
645                 data->send_seq_num++;
646         } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) {
647                 /* Increment if this is the first reply in a trans stream or a
648                  * packet that doesn't belong to this stream (different mid). */
649                 data->send_seq_num++;
650         }
651 }
652
653 /***********************************************************
654  Is an incoming packet an oplock break reply ?
655 ************************************************************/
656
657 static BOOL is_oplock_break(char *inbuf)
658 {
659         if (CVAL(inbuf,smb_com) != SMBlockingX)
660                 return False;
661
662         if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE))
663                 return False;
664
665         DEBUG(10,("is_oplock_break: Packet is oplock break\n"));
666         return True;
667 }
668
669 /***********************************************************
670  SMB signing - Server implementation - check a MAC sent by server.
671 ************************************************************/
672
673 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
674 {
675         BOOL good;
676         struct smb_basic_signing_context *data = si->signing_context;
677         uint32 reply_seq_number = data->send_seq_num;
678         uint32 saved_seq;
679         unsigned char calc_md5_mac[16];
680         unsigned char *server_sent_mac;
681         uint mid;
682
683         if (!si->doing_signing)
684                 return True;
685
686         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
687                 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
688                 return False;
689         }
690
691         mid = SVAL(inbuf, smb_mid);
692
693         /* Is this part of a trans stream ? */
694         if (data->trans_info && (data->trans_info->mid == mid)) {
695                 /* If so we don't increment the sequence. */
696                 reply_seq_number = data->trans_info->reply_seq_num;
697         } else {
698                 /* We always increment the sequence number. */
699                 data->send_seq_num++;
700
701                 /* If we get an asynchronous oplock break reply and there
702                  * isn't a reply pending we need to re-sync the sequence
703                  * number.
704                  */
705                 if (is_oplock_break(inbuf)) {
706                         DEBUG(10,("srv_check_incoming_message: oplock break at seq num %u\n", data->send_seq_num));
707                         data->send_seq_num++;
708                 }
709         }
710
711         saved_seq = reply_seq_number;
712         simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
713
714         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
715         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
716         
717         if (!good) {
718
719                 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
720                                         (unsigned int)saved_seq));
721                 dump_data(5, (const char *)calc_md5_mac, 8);
722                 
723                 DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
724                                         (unsigned int)saved_seq));
725                 dump_data(5, (const char *)server_sent_mac, 8);
726
727 #if 1 /* JRATEST */
728                 {
729                         int i;
730                         reply_seq_number -= 5;
731                         for (i = 0; i < 10; i++, reply_seq_number++) {
732                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
733                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
734                                         DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
735 We were expecting seq %u\n", reply_seq_number, saved_seq ));
736                                         break;
737                                 }
738                         }
739                 }
740 #endif /* JRATEST */
741
742         } else {
743                 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));
744                 dump_data(10, (const char *)server_sent_mac, 8);
745         }
746         return signing_good(inbuf, si, good, saved_seq);
747 }
748
749 /***********************************************************
750  SMB signing - server API's.
751 ************************************************************/
752
753 static struct smb_sign_info srv_sign_info = {
754         null_sign_outgoing_message,
755         null_check_incoming_message,
756         null_free_signing_context,
757         NULL,
758         False,
759         False,
760         False,
761         False
762 };
763
764 /***********************************************************
765  Turn signing off or on for oplock break code.
766 ************************************************************/
767
768 BOOL srv_oplock_set_signing(BOOL onoff)
769 {
770         BOOL ret = srv_sign_info.doing_signing;
771         srv_sign_info.doing_signing = onoff;
772         return ret;
773 }
774
775 /***********************************************************
776  Called to validate an incoming packet from the client.
777 ************************************************************/
778
779 BOOL srv_check_sign_mac(char *inbuf)
780 {
781         /* Check if it's a session keepalive. */
782         if(CVAL(inbuf,0) == SMBkeepalive)
783                 return True;
784
785         return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info);
786 }
787
788 /***********************************************************
789  Called to sign an outgoing packet to the client.
790 ************************************************************/
791
792 void srv_calculate_sign_mac(char *outbuf)
793 {
794         /* Check if it's a session keepalive. */
795         /* JRA Paranioa test - do we ever generate these in the server ? */
796         if(CVAL(outbuf,0) == SMBkeepalive)
797                 return;
798
799         srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
800 }
801
802 /***********************************************************
803  Called by server to defer an outgoing packet.
804 ************************************************************/
805
806 void srv_defer_sign_response(uint16 mid)
807 {
808         struct smb_basic_signing_context *data;
809
810         if (!srv_sign_info.doing_signing)
811                 return;
812
813         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
814
815         if (!data)
816                 return;
817
818         store_sequence_for_reply(&data->outstanding_packet_list, 
819                                  mid, data->send_seq_num);
820         data->send_seq_num++;
821 }
822
823 /***********************************************************
824  Called to remove sequence records when a deferred packet is
825  cancelled by mid. This should never find one....
826 ************************************************************/
827
828 void srv_cancel_sign_response(uint16 mid)
829 {
830         struct smb_basic_signing_context *data;
831         uint32 dummy_seq;
832
833         if (!srv_sign_info.doing_signing)
834                 return;
835
836         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
837
838         if (!data)
839                 return;
840
841         DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
842
843         while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
844                 ;
845 }
846
847 /***********************************************************
848  Called by server negprot when signing has been negotiated.
849 ************************************************************/
850
851 void srv_set_signing_negotiated(void)
852 {
853         srv_sign_info.allow_smb_signing = True;
854         srv_sign_info.negotiated_smb_signing = True;
855         if (lp_server_signing() == Required)
856                 srv_sign_info.mandatory_signing = True;
857
858         srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
859         srv_sign_info.check_incoming_message = temp_check_incoming_message;
860         srv_sign_info.free_signing_context = temp_free_signing_context;
861 }
862
863 /***********************************************************
864  Returns whether signing is active. We can't use sendfile or raw
865  reads/writes if it is.
866 ************************************************************/
867
868 BOOL srv_is_signing_active(void)
869 {
870         return srv_sign_info.doing_signing;
871 }
872
873 /***********************************************************
874  Tell server code we are in a multiple trans reply state.
875 ************************************************************/
876
877 void srv_signing_trans_start(uint16 mid)
878 {
879         struct smb_basic_signing_context *data;
880
881         if (!srv_sign_info.doing_signing)
882                 return;
883
884         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
885         if (!data)
886                 return;
887
888         data->trans_info = smb_xmalloc(sizeof(struct trans_info_context));
889         ZERO_STRUCTP(data->trans_info);
890
891         data->trans_info->reply_seq_num = data->send_seq_num-1;
892         data->trans_info->mid = mid;
893         data->trans_info->send_seq_num = data->send_seq_num;
894
895         DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \
896 data->send_seq_num = %u\n",
897                         (unsigned int)mid,
898                         (unsigned int)data->trans_info->reply_seq_num,
899                         (unsigned int)data->trans_info->send_seq_num,
900                         (unsigned int)data->send_seq_num ));
901 }
902
903 /***********************************************************
904  Tell server code we are out of a multiple trans reply state.
905 ************************************************************/
906
907 void srv_signing_trans_stop(void)
908 {
909         struct smb_basic_signing_context *data;
910
911         if (!srv_sign_info.doing_signing)
912                 return;
913
914         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
915         if (!data || !data->trans_info)
916                 return;
917
918         DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \
919 data->send_seq_num = %u\n",
920                         (unsigned int)data->trans_info->mid,
921                         (unsigned int)data->trans_info->reply_seq_num,
922                         (unsigned int)data->trans_info->send_seq_num,
923                         (unsigned int)data->send_seq_num ));
924
925         SAFE_FREE(data->trans_info);
926         data->trans_info = NULL;
927 }
928
929 /***********************************************************
930  Turn on signing from this packet onwards. 
931 ************************************************************/
932
933 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
934 {
935         struct smb_basic_signing_context *data;
936
937         if (!user_session_key.length)
938                 return;
939
940         if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
941                 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
942                         (unsigned int)srv_sign_info.negotiated_smb_signing,
943                         (unsigned int)srv_sign_info.mandatory_signing ));
944                 return;
945         }
946
947         /* Once we've turned on, ignore any more sessionsetups. */
948         if (srv_sign_info.doing_signing) {
949                 return;
950         }
951         
952         if (srv_sign_info.free_signing_context)
953                 srv_sign_info.free_signing_context(&srv_sign_info);
954         
955         srv_sign_info.doing_signing = True;
956
957         data = smb_xmalloc(sizeof(*data));
958         memset(data, '\0', sizeof(*data));
959
960         srv_sign_info.signing_context = data;
961         
962         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
963
964         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
965         if (response.length)
966                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
967
968         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
969
970         /* Initialise the sequence number */
971         data->send_seq_num = 0;
972
973         /* Initialise the list of outstanding packets */
974         data->outstanding_packet_list = NULL;
975
976         srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
977         srv_sign_info.check_incoming_message = srv_check_incoming_message;
978         srv_sign_info.free_signing_context = simple_free_signing_context;
979 }