r15018: Merge Volker's ipc/trans2/nttrans changes over
[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 struct smb_basic_signing_context {
32         DATA_BLOB mac_key;
33         uint32 send_seq_num;
34         struct outstanding_packet_lookup *outstanding_packet_list;
35 };
36
37 static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, 
38                                      uint16 mid, uint32 reply_seq_num)
39 {
40         struct outstanding_packet_lookup *t;
41
42         /* Ensure we only add a mid once. */
43         for (t = *list; t; t = t->next) {
44                 if (t->mid == mid) {
45                         return False;
46                 }
47         }
48
49         t = SMB_XMALLOC_P(struct outstanding_packet_lookup);
50         ZERO_STRUCTP(t);
51
52         t->mid = mid;
53         t->reply_seq_num = reply_seq_num;
54
55         /*
56          * Add to the *start* of the list not the end of the list.
57          * This ensures that the *last* send sequence with this mid
58          * is returned by preference.
59          * This can happen if the mid wraps and one of the early
60          * mid numbers didn't get a reply and is still lurking on
61          * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>.
62          */
63
64         DLIST_ADD(*list, t);
65         DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
66                         (unsigned int)reply_seq_num, (unsigned int)mid ));
67         return True;
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 must_be_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 must_be_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 (!must_be_ok) {
216                                 return True;
217                         }
218                         /* Non-mandatory signing - just turn off if this is the first bad packet.. */
219                         DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n"
220                                   "isn't sending correct signatures. Turning 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 (!must_be_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 #if 0
251         /* JRA - apparently this is incorrect. */
252         unsigned char key_buf[16];
253 #endif
254
255         /*
256          * Firstly put the sequence number into the first 4 bytes.
257          * and zero out the next 4 bytes.
258          *
259          * We do this here, to avoid modifying the packet.
260          */
261
262         DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
263
264         SIVAL(sequence_buf, 0, seq_number);
265         SIVAL(sequence_buf, 4, 0);
266
267         /* Calculate the 16 byte MAC - but don't alter the data in the
268            incoming packet.
269            
270            This makes for a bit of fussing about, but it's not too bad.
271         */
272         MD5Init(&md5_ctx);
273
274         /* intialise with the key */
275         MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length); 
276 #if 0
277         /* JRA - apparently this is incorrect. */
278         /* NB. When making and verifying SMB signatures, Windows apparently
279                 zero-pads the key to 128 bits if it isn't long enough.
280                 From Nalin Dahyabhai <nalin@redhat.com> */
281         if (data->mac_key.length < sizeof(key_buf)) {
282                 memset(key_buf, 0, sizeof(key_buf));
283                 MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length);
284         }
285 #endif
286
287         /* copy in the first bit of the SMB header */
288         MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
289
290         /* copy in the sequence number, instead of the signature */
291         MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
292
293         /* copy in the rest of the packet in, skipping the signature */
294         MD5Update(&md5_ctx, buf + offset_end_of_sig, 
295                   smb_len(buf) - (offset_end_of_sig - 4));
296
297         /* calculate the MD5 sig */ 
298         MD5Final(calc_md5_mac, &md5_ctx);
299 }
300
301
302 /***********************************************************
303  SMB signing - Client implementation - send the MAC.
304 ************************************************************/
305
306 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
307 {
308         unsigned char calc_md5_mac[16];
309         struct smb_basic_signing_context *data = si->signing_context;
310
311         if (!si->doing_signing)
312                 return;
313
314         /* JRA Paranioa test - we should be able to get rid of this... */
315         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
316                 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
317                                         smb_len(outbuf) ));
318                 abort();
319         }
320
321         /* mark the packet as signed - BEFORE we sign it...*/
322         mark_packet_signed(outbuf);
323
324         simple_packet_signature(data, (const unsigned char *)outbuf,
325                                 data->send_seq_num, calc_md5_mac);
326
327         DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
328         dump_data(10, (const char *)calc_md5_mac, 8);
329
330         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
331
332 /*      cli->outbuf[smb_ss_field+2]=0; 
333         Uncomment this to test if the remote server actually verifies signatures...*/
334
335         data->send_seq_num += 2;
336 }
337
338 /***********************************************************
339  SMB signing - Client implementation - check a MAC sent by server.
340 ************************************************************/
341
342 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
343 {
344         BOOL good;
345         uint32 reply_seq_number;
346         unsigned char calc_md5_mac[16];
347         unsigned char *server_sent_mac;
348
349         struct smb_basic_signing_context *data = si->signing_context;
350
351         if (!si->doing_signing)
352                 return True;
353
354         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
355                 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
356                 return False;
357         }
358
359         reply_seq_number = data->send_seq_num - 1;
360         simple_packet_signature(data, (const unsigned char *)inbuf,
361                                 reply_seq_number, calc_md5_mac);
362
363         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
364         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
365         
366         if (!good) {
367                 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
368                 dump_data(5, (const char *)calc_md5_mac, 8);
369                 
370                 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
371                 dump_data(5, (const char *)server_sent_mac, 8);
372 #if 1 /* JRATEST */
373                 {
374                         int i;
375                         for (i = -5; i < 5; i++) {
376                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number+i, calc_md5_mac);
377                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
378                                         DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
379 We were expecting seq %u\n", reply_seq_number+i, reply_seq_number ));
380                                         break;
381                                 }
382                         }
383                 }
384 #endif /* JRATEST */
385
386         } else {
387                 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
388                 dump_data(10, (const char *)server_sent_mac, 8);
389         }
390         return signing_good(inbuf, si, good, reply_seq_number, must_be_ok);
391 }
392
393 /***********************************************************
394  SMB signing - Simple implementation - free signing context
395 ************************************************************/
396
397 static void simple_free_signing_context(struct smb_sign_info *si)
398 {
399         struct smb_basic_signing_context *data = si->signing_context;
400         struct outstanding_packet_lookup *list;
401         struct outstanding_packet_lookup *next;
402         
403         for (list = data->outstanding_packet_list; list; list = next) {
404                 next = list->next;
405                 DLIST_REMOVE(data->outstanding_packet_list, list);
406                 SAFE_FREE(list);
407         }
408
409         data_blob_free(&data->mac_key);
410
411         SAFE_FREE(si->signing_context);
412
413         return;
414 }
415
416 /***********************************************************
417  SMB signing - Simple implementation - setup the MAC key.
418 ************************************************************/
419
420 BOOL cli_simple_set_signing(struct cli_state *cli,
421                             const DATA_BLOB user_session_key,
422                             const DATA_BLOB response)
423 {
424         struct smb_basic_signing_context *data;
425
426         if (!user_session_key.length)
427                 return False;
428
429         if (!cli_set_smb_signing_common(cli)) {
430                 return False;
431         }
432
433         if (!set_smb_signing_real_common(&cli->sign_info)) {
434                 return False;
435         }
436
437         data = SMB_XMALLOC_P(struct smb_basic_signing_context);
438         memset(data, '\0', sizeof(*data));
439
440         cli->sign_info.signing_context = data;
441         
442         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
443
444         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
445
446         DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
447         dump_data(10, (const char *)user_session_key.data, user_session_key.length);
448
449         if (response.length) {
450                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
451                 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
452                 dump_data(10, (const char *)response.data, response.length);
453         } else {
454                 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
455         }
456
457         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
458
459         /* Initialise the sequence number */
460         data->send_seq_num = 0;
461
462         /* Initialise the list of outstanding packets */
463         data->outstanding_packet_list = NULL;
464
465         cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
466         cli->sign_info.check_incoming_message = client_check_incoming_message;
467         cli->sign_info.free_signing_context = simple_free_signing_context;
468
469         return True;
470 }
471
472 /***********************************************************
473  SMB signing - TEMP implementation - calculate a MAC to send.
474 ************************************************************/
475
476 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
477 {
478         /* mark the packet as signed - BEFORE we sign it...*/
479         mark_packet_signed(outbuf);
480
481         /* I wonder what BSRSPYL stands for - but this is what MS 
482            actually sends! */
483         memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
484         return;
485 }
486
487 /***********************************************************
488  SMB signing - TEMP implementation - check a MAC sent by server.
489 ************************************************************/
490
491 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
492 {
493         return True;
494 }
495
496 /***********************************************************
497  SMB signing - TEMP implementation - free signing context
498 ************************************************************/
499
500 static void temp_free_signing_context(struct smb_sign_info *si)
501 {
502         return;
503 }
504
505 /***********************************************************
506  SMB signing - NULL implementation - setup the MAC key.
507 ************************************************************/
508
509 BOOL cli_null_set_signing(struct cli_state *cli)
510 {
511         return null_set_signing(&cli->sign_info);
512 }
513
514 /***********************************************************
515  SMB signing - temp implementation - setup the MAC key.
516 ************************************************************/
517
518 BOOL cli_temp_set_signing(struct cli_state *cli)
519 {
520         if (!cli_set_smb_signing_common(cli)) {
521                 return False;
522         }
523
524         cli->sign_info.signing_context = NULL;
525         
526         cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
527         cli->sign_info.check_incoming_message = temp_check_incoming_message;
528         cli->sign_info.free_signing_context = temp_free_signing_context;
529
530         return True;
531 }
532
533 void cli_free_signing_context(struct cli_state *cli)
534 {
535         free_signing_context(&cli->sign_info);
536 }
537
538 /**
539  * Sign a packet with the current mechanism
540  */
541  
542 void cli_calculate_sign_mac(struct cli_state *cli)
543 {
544         cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
545 }
546
547 /**
548  * Check a packet with the current mechanism
549  * @return False if we had an established signing connection
550  *         which had a bad checksum, True otherwise.
551  */
552  
553 BOOL cli_check_sign_mac(struct cli_state *cli) 
554 {
555         if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
556                 free_signing_context(&cli->sign_info);  
557                 return False;
558         }
559         return True;
560 }
561
562 /***********************************************************
563  SMB signing - Server implementation - send the MAC.
564 ************************************************************/
565
566 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
567 {
568         unsigned char calc_md5_mac[16];
569         struct smb_basic_signing_context *data = si->signing_context;
570         uint32 send_seq_number = data->send_seq_num-1;
571         uint16 mid;
572
573         if (!si->doing_signing) {
574                 return;
575         }
576
577         /* JRA Paranioa test - we should be able to get rid of this... */
578         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
579                 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
580                                         smb_len(outbuf) ));
581                 abort();
582         }
583
584         /* mark the packet as signed - BEFORE we sign it...*/
585         mark_packet_signed(outbuf);
586
587         mid = SVAL(outbuf, smb_mid);
588
589         /* See if this is a reply for a deferred packet. */
590         get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
591
592         simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
593
594         DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
595         dump_data(10, (const char *)calc_md5_mac, 8);
596
597         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
598
599 /*      cli->outbuf[smb_ss_field+2]=0; 
600         Uncomment this to test if the remote client actually verifies signatures...*/
601 }
602
603 /***********************************************************
604  SMB signing - Server implementation - check a MAC sent by server.
605 ************************************************************/
606
607 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
608 {
609         BOOL good;
610         struct smb_basic_signing_context *data = si->signing_context;
611         uint32 reply_seq_number = data->send_seq_num;
612         uint32 saved_seq;
613         unsigned char calc_md5_mac[16];
614         unsigned char *server_sent_mac;
615         uint mid;
616
617         if (!si->doing_signing)
618                 return True;
619
620         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
621                 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
622                 return False;
623         }
624
625         mid = SVAL(inbuf, smb_mid);
626
627         /* We always increment the sequence number. */
628         data->send_seq_num += 2;
629
630         saved_seq = reply_seq_number;
631         simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
632
633         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
634         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
635         
636         if (!good) {
637
638                 if (saved_seq) {
639                         DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
640                                         (unsigned int)saved_seq));
641                         dump_data(5, (const char *)calc_md5_mac, 8);
642
643                         DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
644                                                 (unsigned int)reply_seq_number));
645                         dump_data(5, (const char *)server_sent_mac, 8);
646                 }
647                 
648 #if 1 /* JRATEST */
649                 {
650                         int i;
651                         reply_seq_number -= 5;
652                         for (i = 0; i < 10; i++, reply_seq_number++) {
653                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
654                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
655                                         DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
656 We were expecting seq %u\n", reply_seq_number, saved_seq ));
657                                         break;
658                                 }
659                         }
660                 }
661 #endif /* JRATEST */
662
663         } else {
664                 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));
665                 dump_data(10, (const char *)server_sent_mac, 8);
666         }
667
668         return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
669 }
670
671 /***********************************************************
672  SMB signing - server API's.
673 ************************************************************/
674
675 static struct smb_sign_info srv_sign_info = {
676         null_sign_outgoing_message,
677         null_check_incoming_message,
678         null_free_signing_context,
679         NULL,
680         False,
681         False,
682         False,
683         False
684 };
685
686 /***********************************************************
687  Turn signing off or on for oplock break code.
688 ************************************************************/
689
690 BOOL srv_oplock_set_signing(BOOL onoff)
691 {
692         BOOL ret = srv_sign_info.doing_signing;
693         srv_sign_info.doing_signing = onoff;
694         return ret;
695 }
696
697 /***********************************************************
698  Called to validate an incoming packet from the client.
699 ************************************************************/
700
701 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
702 {
703         /* Check if it's a session keepalive. */
704         if(CVAL(inbuf,0) == SMBkeepalive)
705                 return True;
706
707         return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
708 }
709
710 /***********************************************************
711  Called to sign an outgoing packet to the client.
712 ************************************************************/
713
714 void srv_calculate_sign_mac(char *outbuf)
715 {
716         /* Check if it's a session keepalive. */
717         /* JRA Paranioa test - do we ever generate these in the server ? */
718         if(CVAL(outbuf,0) == SMBkeepalive)
719                 return;
720
721         srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
722 }
723
724 /***********************************************************
725  Called by server to defer an outgoing packet.
726 ************************************************************/
727
728 void srv_defer_sign_response(uint16 mid)
729 {
730         struct smb_basic_signing_context *data;
731
732         if (!srv_sign_info.doing_signing)
733                 return;
734
735         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
736
737         if (!data)
738                 return;
739
740         /*
741          * Ensure we only store this mid reply once...
742          */
743
744         store_sequence_for_reply(&data->outstanding_packet_list, mid,
745                                  data->send_seq_num-1);
746 }
747
748 /***********************************************************
749  Called to remove sequence records when a deferred packet is
750  cancelled by mid. This should never find one....
751 ************************************************************/
752
753 void srv_cancel_sign_response(uint16 mid)
754 {
755         struct smb_basic_signing_context *data;
756         uint32 dummy_seq;
757
758         if (!srv_sign_info.doing_signing)
759                 return;
760
761         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
762
763         if (!data)
764                 return;
765
766         DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
767
768         while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
769                 ;
770 }
771
772 /***********************************************************
773  Called by server negprot when signing has been negotiated.
774 ************************************************************/
775
776 void srv_set_signing_negotiated(void)
777 {
778         srv_sign_info.allow_smb_signing = True;
779         srv_sign_info.negotiated_smb_signing = True;
780         if (lp_server_signing() == Required)
781                 srv_sign_info.mandatory_signing = True;
782
783         srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
784         srv_sign_info.check_incoming_message = temp_check_incoming_message;
785         srv_sign_info.free_signing_context = temp_free_signing_context;
786 }
787
788 /***********************************************************
789  Returns whether signing is active. We can't use sendfile or raw
790  reads/writes if it is.
791 ************************************************************/
792
793 BOOL srv_is_signing_active(void)
794 {
795         return srv_sign_info.doing_signing;
796 }
797
798
799 /***********************************************************
800  Returns whether signing is negotiated. We can't use it unless it was
801  in the negprot.  
802 ************************************************************/
803
804 BOOL srv_is_signing_negotiated(void)
805 {
806         return srv_sign_info.negotiated_smb_signing;
807 }
808
809 /***********************************************************
810  Returns whether signing is actually happening
811 ************************************************************/
812
813 BOOL srv_signing_started(void)
814 {
815         struct smb_basic_signing_context *data;
816
817         if (!srv_sign_info.doing_signing) {
818                 return False;
819         }
820
821         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
822         if (!data)
823                 return False;
824
825         if (data->send_seq_num == 0) {
826                 return False;
827         }
828
829         return True;
830 }
831
832 /***********************************************************
833  Turn on signing from this packet onwards. 
834 ************************************************************/
835
836 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
837 {
838         struct smb_basic_signing_context *data;
839
840         if (!user_session_key.length)
841                 return;
842
843         if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
844                 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
845                         (unsigned int)srv_sign_info.negotiated_smb_signing,
846                         (unsigned int)srv_sign_info.mandatory_signing ));
847                 return;
848         }
849
850         /* Once we've turned on, ignore any more sessionsetups. */
851         if (srv_sign_info.doing_signing) {
852                 return;
853         }
854         
855         if (srv_sign_info.free_signing_context)
856                 srv_sign_info.free_signing_context(&srv_sign_info);
857         
858         srv_sign_info.doing_signing = True;
859
860         data = SMB_XMALLOC_P(struct smb_basic_signing_context);
861         memset(data, '\0', sizeof(*data));
862
863         srv_sign_info.signing_context = data;
864         
865         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
866
867         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
868         if (response.length)
869                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
870
871         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
872
873         DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
874                                 BOOLSTR(srv_sign_info.negotiated_smb_signing),
875                                 BOOLSTR(srv_sign_info.mandatory_signing) ));
876
877         /* Initialise the sequence number */
878         data->send_seq_num = 0;
879
880         /* Initialise the list of outstanding packets */
881         data->outstanding_packet_list = NULL;
882
883         srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
884         srv_sign_info.check_incoming_message = srv_check_incoming_message;
885         srv_sign_info.free_signing_context = simple_free_signing_context;
886 }