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