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