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