root/source3/libsmb/smb_signing.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. store_sequence_for_reply
  2. get_sequence_for_reply
  3. set_sequence_can_delete_flag
  4. cli_set_smb_signing_common
  5. set_smb_signing_real_common
  6. mark_packet_signed
  7. null_sign_outgoing_message
  8. null_check_incoming_message
  9. null_free_signing_context
  10. null_set_signing
  11. free_signing_context
  12. signing_good
  13. simple_packet_signature
  14. client_sign_outgoing_message
  15. client_check_incoming_message
  16. simple_free_signing_context
  17. cli_simple_set_signing
  18. temp_sign_outgoing_message
  19. temp_check_incoming_message
  20. temp_free_signing_context
  21. cli_null_set_signing
  22. cli_temp_set_signing
  23. cli_free_signing_context
  24. cli_calculate_sign_mac
  25. cli_check_sign_mac
  26. client_set_trans_sign_state_on
  27. client_set_trans_sign_state_off
  28. client_is_signing_on
  29. srv_sign_outgoing_message
  30. srv_check_incoming_message
  31. srv_oplock_set_signing
  32. srv_check_sign_mac
  33. srv_calculate_sign_mac
  34. srv_defer_sign_response
  35. srv_cancel_sign_response
  36. srv_set_signing_negotiated
  37. srv_is_signing_active
  38. srv_is_signing_negotiated
  39. srv_signing_started
  40. srv_set_signing

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

/* [<][>][^][v][top][bottom][index][help] */