36c4147af8f95107f0d32cf08e0e35973490ab80
[tprouty/samba.git] / source / libsmb / smb_signing.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB Signing Code
4    Copyright (C) Jeremy Allison 2003.
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
25 struct outstanding_packet_lookup {
26         uint16 mid;
27         uint32 reply_seq_num;
28         struct outstanding_packet_lookup *prev, *next;
29 };
30
31 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 void store_sequence_for_reply(struct outstanding_packet_lookup **list, 
38                                      uint16 mid, uint32 reply_seq_num) 
39 {
40         struct outstanding_packet_lookup *t;
41         struct outstanding_packet_lookup *tmp;
42         
43         t = smb_xmalloc(sizeof(*t));
44         ZERO_STRUCTP(t);
45
46         DLIST_ADD_END(*list, t, tmp);
47         t->mid = mid;
48         t->reply_seq_num = reply_seq_num;
49 }
50
51 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
52                                    uint16 mid, uint32 *reply_seq_num) 
53 {
54         struct outstanding_packet_lookup *t;
55
56         for (t = *list; t; t = t->next) {
57                 if (t->mid == mid) {
58                         *reply_seq_num = t->reply_seq_num;
59                         DLIST_REMOVE(*list, t);
60                         SAFE_FREE(t);
61                         return True;
62                 }
63         }
64         DEBUG(0, ("Unexpected incoming packet, it's MID (%u) does not match"
65                   " a MID in our outstanding list!\n", mid));
66         return False;
67 }
68
69 /***********************************************************
70  SMB signing - Common code before we set a new signing implementation
71 ************************************************************/
72
73 static BOOL cli_set_smb_signing_common(struct cli_state *cli) 
74 {
75         if (!cli->sign_info.negotiated_smb_signing 
76             && !cli->sign_info.mandatory_signing) {
77                 return False;
78         }
79
80         if (cli->sign_info.doing_signing) {
81                 return False;
82         }
83         
84         if (cli->sign_info.free_signing_context)
85                 cli->sign_info.free_signing_context(&cli->sign_info);
86
87         /* These calls are INCOMPATIBLE with SMB signing */
88         cli->readbraw_supported = False;
89         cli->writebraw_supported = False;
90         
91         return True;
92 }
93
94 /***********************************************************
95  SMB signing - Common code for 'real' implementations
96 ************************************************************/
97
98 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
99 {
100         if (si->mandatory_signing) {
101                 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
102                 si->doing_signing = True;
103         }
104
105         DEBUG(5, ("SMB signing enabled!\n"));
106
107         return True;
108 }
109
110 static void mark_packet_signed(char *outbuf)
111 {
112         uint16 flags2;
113         flags2 = SVAL(outbuf,smb_flg2);
114         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
115         SSVAL(outbuf,smb_flg2, flags2);
116 }
117
118 /***********************************************************
119  SMB signing - NULL implementation - calculate a MAC to send.
120 ************************************************************/
121
122 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
123 {
124         /* we can't zero out the sig, as we might be trying to send a
125            session request - which is NBT-level, not SMB level and doesn't
126            have the field */
127         return;
128 }
129
130 /***********************************************************
131  SMB signing - NULL implementation - check a MAC sent by server.
132 ************************************************************/
133
134 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
135 {
136         return True;
137 }
138
139 /***********************************************************
140  SMB signing - NULL implementation - free signing context
141 ************************************************************/
142
143 static void null_free_signing_context(struct smb_sign_info *si)
144 {
145         return;
146 }
147
148 /**
149  SMB signing - NULL implementation - setup the MAC key.
150
151  @note Used as an initialisation only - it will not correctly
152        shut down a real signing mechanism
153 */
154
155 static BOOL null_set_signing(struct smb_sign_info *si)
156 {
157         si->signing_context = NULL;
158         
159         si->sign_outgoing_message = null_sign_outgoing_message;
160         si->check_incoming_message = null_check_incoming_message;
161         si->free_signing_context = null_free_signing_context;
162
163         return True;
164 }
165
166 /**
167  * Free the signing context
168  */
169  
170 static void free_signing_context(struct smb_sign_info *si)
171 {
172         if (si->free_signing_context) {
173                 si->free_signing_context(si);
174                 si->signing_context = NULL;
175         }
176
177         null_set_signing(si);
178 }
179
180
181 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) 
182 {
183         DEBUG(10, ("signing_good: got SMB signature of\n"));
184         dump_data(10,&inbuf[smb_ss_field] , 8);
185
186         if (good && !si->doing_signing) {
187                 si->doing_signing = True;
188         }
189
190         if (!good) {
191                 if (si->doing_signing) {
192                         DEBUG(1, ("SMB signature check failed!\n"));
193                         return False;
194                 } else {
195                         DEBUG(3, ("Server did not sign reply correctly\n"));
196                         free_signing_context(si);
197                         return False;
198                 }
199         }
200         return True;
201 }       
202
203 /***********************************************************
204  SMB signing - Simple implementation - calculate a MAC on the packet
205 ************************************************************/
206
207 static void simple_packet_signature(struct smb_basic_signing_context *data, 
208                                     const uchar *buf, uint32 seq_number, 
209                                     unsigned char calc_md5_mac[16])
210 {
211         const size_t offset_end_of_sig = (smb_ss_field + 8);
212         unsigned char sequence_buf[8];
213         struct MD5Context md5_ctx;
214
215         /*
216          * Firstly put the sequence number into the first 4 bytes.
217          * and zero out the next 4 bytes.
218          *
219          * We do this here, to avoid modifying the packet.
220          */
221
222         DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
223
224         SIVAL(sequence_buf, 0, seq_number);
225         SIVAL(sequence_buf, 4, 0);
226
227         /* Calculate the 16 byte MAC - but don't alter the data in the
228            incoming packet.
229            
230            This makes for a bit for fussing about, but it's not too bad.
231         */
232         MD5Init(&md5_ctx);
233
234         /* intialise with the key */
235         MD5Update(&md5_ctx, data->mac_key.data, 
236                   data->mac_key.length); 
237
238         /* copy in the first bit of the SMB header */
239         MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
240
241         /* copy in the sequence number, instead of the signature */
242         MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
243
244         /* copy in the rest of the packet in, skipping the signature */
245         MD5Update(&md5_ctx, buf + offset_end_of_sig, 
246                   smb_len(buf) - (offset_end_of_sig - 4));
247
248         /* calculate the MD5 sig */ 
249         MD5Final(calc_md5_mac, &md5_ctx);
250 }
251
252
253 /***********************************************************
254  SMB signing - Client implementation - send the MAC.
255 ************************************************************/
256
257 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
258 {
259         unsigned char calc_md5_mac[16];
260         struct smb_basic_signing_context *data = si->signing_context;
261
262         if (!si->doing_signing)
263                 return;
264
265         /* JRA Paranioa test - we should be able to get rid of this... */
266         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
267                 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
268                                         smb_len(outbuf) ));
269                 abort();
270         }
271
272         /* mark the packet as signed - BEFORE we sign it...*/
273         mark_packet_signed(outbuf);
274
275         simple_packet_signature(data, outbuf, data->send_seq_num, calc_md5_mac);
276
277         DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
278         dump_data(10, calc_md5_mac, 8);
279
280         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
281
282 /*      cli->outbuf[smb_ss_field+2]=0; 
283         Uncomment this to test if the remote server actually verifies signatures...*/
284
285         data->send_seq_num++;
286         store_sequence_for_reply(&data->outstanding_packet_list, 
287                                  SVAL(outbuf,smb_mid),
288                                  data->send_seq_num);
289         data->send_seq_num++;
290 }
291
292 /***********************************************************
293  SMB signing - Client implementation - check a MAC sent by server.
294 ************************************************************/
295
296 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
297 {
298         BOOL good;
299         uint32 reply_seq_number;
300         unsigned char calc_md5_mac[16];
301         unsigned char *server_sent_mac;
302
303         struct smb_basic_signing_context *data = si->signing_context;
304
305         if (!si->doing_signing)
306                 return True;
307
308         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
309                 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
310                 return False;
311         }
312
313         if (!get_sequence_for_reply(&data->outstanding_packet_list, 
314                                     SVAL(inbuf, smb_mid), 
315                                     &reply_seq_number)) {
316                 return False;
317         }
318
319         simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
320
321         server_sent_mac = &inbuf[smb_ss_field];
322         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
323         
324         if (!good) {
325                 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
326                 dump_data(5, calc_md5_mac, 8);
327                 
328                 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
329                 dump_data(5, server_sent_mac, 8);
330         }
331         return signing_good(inbuf, si, good);
332 }
333
334 /***********************************************************
335  SMB signing - Simple implementation - free signing context
336 ************************************************************/
337
338 static void simple_free_signing_context(struct smb_sign_info *si)
339 {
340         struct smb_basic_signing_context *data = si->signing_context;
341         struct outstanding_packet_lookup *list = data->outstanding_packet_list;
342         
343         while (list) {
344                 struct outstanding_packet_lookup *old_head = list;
345                 DLIST_REMOVE(list, list);
346                 SAFE_FREE(old_head);
347         }
348
349         data_blob_free(&data->mac_key);
350         SAFE_FREE(si->signing_context);
351
352         return;
353 }
354
355 /***********************************************************
356  SMB signing - Simple implementation - setup the MAC key.
357 ************************************************************/
358
359 BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[16], const DATA_BLOB response)
360 {
361         struct smb_basic_signing_context *data;
362
363         if (!user_session_key)
364                 return False;
365
366         if (!cli_set_smb_signing_common(cli)) {
367                 return False;
368         }
369
370         if (!set_smb_signing_real_common(&cli->sign_info)) {
371                 return False;
372         }
373
374         data = smb_xmalloc(sizeof(*data));
375
376         cli->sign_info.signing_context = data;
377         
378         data->mac_key = data_blob(NULL, response.length + 16);
379
380         memcpy(&data->mac_key.data[0], user_session_key, 16);
381
382         DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
383         dump_data(10, user_session_key, 16);
384
385         if (response.length) {
386                 memcpy(&data->mac_key.data[16],response.data, response.length);
387                 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
388                 dump_data(10, response.data, response.length);
389         } else {
390                 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
391         }
392
393         /* Initialise the sequence number */
394         data->send_seq_num = 0;
395
396         /* Initialise the list of outstanding packets */
397         data->outstanding_packet_list = NULL;
398
399         cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
400         cli->sign_info.check_incoming_message = client_check_incoming_message;
401         cli->sign_info.free_signing_context = simple_free_signing_context;
402
403         return True;
404 }
405
406 /***********************************************************
407  SMB signing - TEMP implementation - calculate a MAC to send.
408 ************************************************************/
409
410 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
411 {
412         /* mark the packet as signed - BEFORE we sign it...*/
413         mark_packet_signed(outbuf);
414
415         /* I wonder what BSRSPYL stands for - but this is what MS 
416            actually sends! */
417         memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
418         return;
419 }
420
421 /***********************************************************
422  SMB signing - TEMP implementation - check a MAC sent by server.
423 ************************************************************/
424
425 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
426 {
427         return True;
428 }
429
430 /***********************************************************
431  SMB signing - TEMP implementation - free signing context
432 ************************************************************/
433
434 static void temp_free_signing_context(struct smb_sign_info *si)
435 {
436         return;
437 }
438
439 /***********************************************************
440  SMB signing - NULL implementation - setup the MAC key.
441 ************************************************************/
442
443 BOOL cli_null_set_signing(struct cli_state *cli)
444 {
445         return null_set_signing(&cli->sign_info);
446 }
447
448 /***********************************************************
449  SMB signing - temp implementation - setup the MAC key.
450 ************************************************************/
451
452 BOOL cli_temp_set_signing(struct cli_state *cli)
453 {
454         if (!cli_set_smb_signing_common(cli)) {
455                 return False;
456         }
457
458         cli->sign_info.signing_context = NULL;
459         
460         cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
461         cli->sign_info.check_incoming_message = temp_check_incoming_message;
462         cli->sign_info.free_signing_context = temp_free_signing_context;
463
464         return True;
465 }
466
467 void cli_free_signing_context(struct cli_state *cli)
468 {
469         free_signing_context(&cli->sign_info);
470 }
471
472 /**
473  * Sign a packet with the current mechanism
474  */
475  
476 void cli_calculate_sign_mac(struct cli_state *cli)
477 {
478         cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
479 }
480
481 /**
482  * Check a packet with the current mechanism
483  * @return False if we had an established signing connection
484  *         which had a bad checksum, True otherwise.
485  */
486  
487 BOOL cli_check_sign_mac(struct cli_state *cli) 
488 {
489         if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) {
490                 free_signing_context(&cli->sign_info);  
491                 return False;
492         }
493         return True;
494 }
495
496 /***********************************************************
497  SMB signing - Server implementation - send the MAC.
498 ************************************************************/
499
500 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
501 {
502         unsigned char calc_md5_mac[16];
503         struct smb_basic_signing_context *data = si->signing_context;
504
505         if (!si->doing_signing)
506                 return;
507
508         /* JRA Paranioa test - we should be able to get rid of this... */
509         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
510                 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
511                                         smb_len(outbuf) ));
512                 abort();
513         }
514
515         /* mark the packet as signed - BEFORE we sign it...*/
516         mark_packet_signed(outbuf);
517
518         simple_packet_signature(data, outbuf, data->send_seq_num, calc_md5_mac);
519
520         DEBUG(10, ("srv_sign_outgoing_message: sent SMB signature of\n"));
521         dump_data(10, calc_md5_mac, 8);
522
523         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
524
525 /*      cli->outbuf[smb_ss_field+2]=0; 
526         Uncomment this to test if the remote server actually verifies signatures...*/
527
528         data->send_seq_num++;
529 #if 0 /* JRATEST */
530         store_sequence_for_reply(&data->outstanding_packet_list, 
531                                  SVAL(outbuf,smb_mid),
532                                  data->send_seq_num);
533         data->send_seq_num++;
534 #endif /* JRATEST */
535 }
536
537 /***********************************************************
538  SMB signing - Server implementation - check a MAC sent by server.
539 ************************************************************/
540
541 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
542 {
543         BOOL good;
544         uint32 reply_seq_number;
545         unsigned char calc_md5_mac[16];
546         unsigned char *server_sent_mac;
547
548         struct smb_basic_signing_context *data = si->signing_context;
549
550         if (!si->doing_signing)
551                 return True;
552
553         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
554                 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
555                 return False;
556         }
557
558 #if 0 /* JRATEST */
559         if (!get_sequence_for_reply(&data->outstanding_packet_list, 
560                                     SVAL(inbuf, smb_mid), 
561                                     &reply_seq_number)) {
562                 return False;
563         }
564 #else /* JRATEST */
565         reply_seq_number = data->send_seq_num;
566         data->send_seq_num++;
567 #endif /* JRATEST */
568
569         simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
570
571         server_sent_mac = &inbuf[smb_ss_field];
572         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
573         
574         if (!good) {
575                 DEBUG(5, ("srv_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
576                 dump_data(5, calc_md5_mac, 8);
577                 
578                 DEBUG(5, ("srv_check_incoming_message: BAD SIG: got SMB signature of\n"));
579                 dump_data(5, server_sent_mac, 8);
580         }
581         return signing_good(inbuf, si, good);
582 }
583
584 /***********************************************************
585  SMB signing - server API's.
586 ************************************************************/
587
588 static struct smb_sign_info srv_sign_info = {
589         null_sign_outgoing_message,
590         null_check_incoming_message,
591         null_free_signing_context,
592         NULL,
593         False,
594         False,
595         False,
596         False
597 };
598
599 /***********************************************************
600  Turn signing off or on for oplock break code.
601 ************************************************************/
602
603 BOOL srv_oplock_set_signing(BOOL onoff)
604 {
605         BOOL ret = srv_sign_info.doing_signing;
606         srv_sign_info.doing_signing = onoff;
607         return ret;
608 }
609
610 /***********************************************************
611  Called to validate an incoming packet from the client.
612 ************************************************************/
613
614 BOOL srv_check_sign_mac(char *inbuf)
615 {
616         /* Check if it's a session keepalive. */
617         if(CVAL(inbuf,0) == SMBkeepalive)
618                 return True;
619
620         return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info);
621 }
622
623 /***********************************************************
624  Called to sign an outgoing packet to the client.
625 ************************************************************/
626
627 void srv_calculate_sign_mac(char *outbuf)
628 {
629         /* Check if it's a session keepalive. */
630         /* JRA Paranioa test - do we ever generate these in the server ? */
631         if(CVAL(outbuf,0) == SMBkeepalive)
632                 return;
633
634         srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
635 }
636
637 /***********************************************************
638  Called by server negprot when signing has been negotiated.
639 ************************************************************/
640
641 void srv_set_signing_negotiated(void)
642 {
643         srv_sign_info.allow_smb_signing = True;
644         srv_sign_info.negotiated_smb_signing = True;
645         if (lp_server_signing() == Required)
646                 srv_sign_info.mandatory_signing = True;
647
648         srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
649         srv_sign_info.check_incoming_message = temp_check_incoming_message;
650         srv_sign_info.free_signing_context = temp_free_signing_context;
651 }
652
653 /***********************************************************
654  Returns whether signing is active. We can't use sendfile or raw
655  reads/writes if it is.
656 ************************************************************/
657
658 BOOL srv_is_signing_active(void)
659 {
660         return srv_sign_info.doing_signing;
661 }
662
663 /***********************************************************
664  Turn on signing from this packet onwards. 
665 ************************************************************/
666
667 void srv_set_signing(const uchar user_session_key[16], const DATA_BLOB response)
668 {
669         struct smb_basic_signing_context *data;
670
671         if (!user_session_key)
672                 return;
673
674         if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
675                 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
676                         (unsigned int)srv_sign_info.negotiated_smb_signing,
677                         (unsigned int)srv_sign_info.mandatory_signing ));
678                 return;
679         }
680
681         /* Once we've turned on, ignore any more sessionsetups. */
682         if (srv_sign_info.doing_signing) {
683                 return;
684         }
685         
686         if (srv_sign_info.free_signing_context)
687                 srv_sign_info.free_signing_context(&srv_sign_info);
688         
689         srv_sign_info.doing_signing = True;
690
691         data = smb_xmalloc(sizeof(*data));
692
693         srv_sign_info.signing_context = data;
694         
695         data->mac_key = data_blob(NULL, response.length + 16);
696
697         memcpy(&data->mac_key.data[0], user_session_key, 16);
698         if (response.length)
699                 memcpy(&data->mac_key.data[16],response.data, response.length);
700
701         /* Initialise the sequence number */
702         data->send_seq_num = 0;
703
704         /* Initialise the list of outstanding packets */
705         data->outstanding_packet_list = NULL;
706
707         srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
708         srv_sign_info.check_incoming_message = srv_check_incoming_message;
709         srv_sign_info.free_signing_context = simple_free_signing_context;
710 }