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