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