libsmb/smb_signing.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    SMB Signing Code
00004    Copyright (C) Jeremy Allison 2003.
00005    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
00006    
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 
00024 /* Lookup a packet's MID (multiplex id) and figure out it's sequence number */
00025 struct outstanding_packet_lookup {
00026         struct outstanding_packet_lookup *prev, *next;
00027         uint16 mid;
00028         uint32 reply_seq_num;
00029         BOOL can_delete; /* Set to False in trans state. */
00030 };
00031 
00032 struct smb_basic_signing_context {
00033         DATA_BLOB mac_key;
00034         uint32 send_seq_num;
00035         struct outstanding_packet_lookup *outstanding_packet_list;
00036 };
00037 
00038 static BOOL store_sequence_for_reply(struct outstanding_packet_lookup **list, 
00039                                      uint16 mid, uint32 reply_seq_num)
00040 {
00041         struct outstanding_packet_lookup *t;
00042 
00043         /* Ensure we only add a mid once. */
00044         for (t = *list; t; t = t->next) {
00045                 if (t->mid == mid) {
00046                         return False;
00047                 }
00048         }
00049 
00050         t = SMB_XMALLOC_P(struct outstanding_packet_lookup);
00051         ZERO_STRUCTP(t);
00052 
00053         t->mid = mid;
00054         t->reply_seq_num = reply_seq_num;
00055         t->can_delete = True;
00056 
00057         /*
00058          * Add to the *start* of the list not the end of the list.
00059          * This ensures that the *last* send sequence with this mid
00060          * is returned by preference.
00061          * This can happen if the mid wraps and one of the early
00062          * mid numbers didn't get a reply and is still lurking on
00063          * the list. JRA. Found by Fran Fabrizio <fran@cis.uab.edu>.
00064          */
00065 
00066         DLIST_ADD(*list, t);
00067         DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n",
00068                         (unsigned int)reply_seq_num, (unsigned int)mid ));
00069         return True;
00070 }
00071 
00072 static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list,
00073                                    uint16 mid, uint32 *reply_seq_num)
00074 {
00075         struct outstanding_packet_lookup *t;
00076 
00077         for (t = *list; t; t = t->next) {
00078                 if (t->mid == mid) {
00079                         *reply_seq_num = t->reply_seq_num;
00080                         DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n",
00081                                 (unsigned int)t->reply_seq_num, (unsigned int)t->mid ));
00082                         if (t->can_delete) {
00083                                 DLIST_REMOVE(*list, t);
00084                                 SAFE_FREE(t);
00085                         }
00086                         return True;
00087                 }
00088         }
00089         return False;
00090 }
00091 
00092 static BOOL set_sequence_can_delete_flag(struct outstanding_packet_lookup **list, uint16 mid, BOOL can_delete_entry)
00093 {
00094         struct outstanding_packet_lookup *t;
00095 
00096         for (t = *list; t; t = t->next) {
00097                 if (t->mid == mid) {
00098                         t->can_delete = can_delete_entry;
00099                         return True;
00100                 }
00101         }
00102         return False;
00103 }
00104 
00105 /***********************************************************
00106  SMB signing - Common code before we set a new signing implementation
00107 ************************************************************/
00108 
00109 static BOOL cli_set_smb_signing_common(struct cli_state *cli) 
00110 {
00111         if (!cli->sign_info.allow_smb_signing) {
00112                 return False;
00113         }
00114 
00115         if (!cli->sign_info.negotiated_smb_signing 
00116             && !cli->sign_info.mandatory_signing) {
00117                 return False;
00118         }
00119 
00120         if (cli->sign_info.doing_signing) {
00121                 return False;
00122         }
00123         
00124         if (cli->sign_info.free_signing_context)
00125                 cli->sign_info.free_signing_context(&cli->sign_info);
00126 
00127         /* These calls are INCOMPATIBLE with SMB signing */
00128         cli->readbraw_supported = False;
00129         cli->writebraw_supported = False;
00130         
00131         return True;
00132 }
00133 
00134 /***********************************************************
00135  SMB signing - Common code for 'real' implementations
00136 ************************************************************/
00137 
00138 static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
00139 {
00140         if (si->mandatory_signing) {
00141                 DEBUG(5, ("Mandatory SMB signing enabled!\n"));
00142         }
00143 
00144         si->doing_signing = True;
00145         DEBUG(5, ("SMB signing enabled!\n"));
00146 
00147         return True;
00148 }
00149 
00150 static void mark_packet_signed(char *outbuf)
00151 {
00152         uint16 flags2;
00153         flags2 = SVAL(outbuf,smb_flg2);
00154         flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
00155         SSVAL(outbuf,smb_flg2, flags2);
00156 }
00157 
00158 /***********************************************************
00159  SMB signing - NULL implementation - calculate a MAC to send.
00160 ************************************************************/
00161 
00162 static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
00163 {
00164         /* we can't zero out the sig, as we might be trying to send a
00165            session request - which is NBT-level, not SMB level and doesn't
00166            have the field */
00167         return;
00168 }
00169 
00170 /***********************************************************
00171  SMB signing - NULL implementation - check a MAC sent by server.
00172 ************************************************************/
00173 
00174 static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
00175 {
00176         return True;
00177 }
00178 
00179 /***********************************************************
00180  SMB signing - NULL implementation - free signing context
00181 ************************************************************/
00182 
00183 static void null_free_signing_context(struct smb_sign_info *si)
00184 {
00185         return;
00186 }
00187 
00188 /**
00189  SMB signing - NULL implementation - setup the MAC key.
00190 
00191  @note Used as an initialisation only - it will not correctly
00192        shut down a real signing mechanism
00193 */
00194 
00195 static BOOL null_set_signing(struct smb_sign_info *si)
00196 {
00197         si->signing_context = NULL;
00198         
00199         si->sign_outgoing_message = null_sign_outgoing_message;
00200         si->check_incoming_message = null_check_incoming_message;
00201         si->free_signing_context = null_free_signing_context;
00202 
00203         return True;
00204 }
00205 
00206 /**
00207  * Free the signing context
00208  */
00209  
00210 static void free_signing_context(struct smb_sign_info *si)
00211 {
00212         if (si->free_signing_context) {
00213                 si->free_signing_context(si);
00214                 si->signing_context = NULL;
00215         }
00216 
00217         null_set_signing(si);
00218 }
00219 
00220 
00221 static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok) 
00222 {
00223         if (good) {
00224 
00225                 if (!si->doing_signing) {
00226                         si->doing_signing = True;
00227                 }
00228                 
00229                 if (!si->seen_valid) {
00230                         si->seen_valid = True;
00231                 }
00232 
00233         } else {
00234                 if (!si->mandatory_signing && !si->seen_valid) {
00235 
00236                         if (!must_be_ok) {
00237                                 return True;
00238                         }
00239                         /* Non-mandatory signing - just turn off if this is the first bad packet.. */
00240                         DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n"
00241                                   "isn't sending correct signatures. Turning off.\n"));
00242                         si->negotiated_smb_signing = False;
00243                         si->allow_smb_signing = False;
00244                         si->doing_signing = False;
00245                         free_signing_context(si);
00246                         return True;
00247                 } else if (!must_be_ok) {
00248                         /* This packet is known to be unsigned */
00249                         return True;
00250                 } else {
00251                         /* Mandatory signing or bad packet after signing started - fail and disconnect. */
00252                         if (seq)
00253                                 DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
00254                         return False;
00255                 }
00256         }
00257         return True;
00258 }       
00259 
00260 /***********************************************************
00261  SMB signing - Simple implementation - calculate a MAC on the packet
00262 ************************************************************/
00263 
00264 static void simple_packet_signature(struct smb_basic_signing_context *data, 
00265                                     const uchar *buf, uint32 seq_number, 
00266                                     unsigned char calc_md5_mac[16])
00267 {
00268         const size_t offset_end_of_sig = (smb_ss_field + 8);
00269         unsigned char sequence_buf[8];
00270         struct MD5Context md5_ctx;
00271 #if 0
00272         /* JRA - apparently this is incorrect. */
00273         unsigned char key_buf[16];
00274 #endif
00275 
00276         /*
00277          * Firstly put the sequence number into the first 4 bytes.
00278          * and zero out the next 4 bytes.
00279          *
00280          * We do this here, to avoid modifying the packet.
00281          */
00282 
00283         DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number ));
00284 
00285         SIVAL(sequence_buf, 0, seq_number);
00286         SIVAL(sequence_buf, 4, 0);
00287 
00288         /* Calculate the 16 byte MAC - but don't alter the data in the
00289            incoming packet.
00290            
00291            This makes for a bit of fussing about, but it's not too bad.
00292         */
00293         MD5Init(&md5_ctx);
00294 
00295         /* intialise with the key */
00296         MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length); 
00297 #if 0
00298         /* JRA - apparently this is incorrect. */
00299         /* NB. When making and verifying SMB signatures, Windows apparently
00300                 zero-pads the key to 128 bits if it isn't long enough.
00301                 From Nalin Dahyabhai <nalin@redhat.com> */
00302         if (data->mac_key.length < sizeof(key_buf)) {
00303                 memset(key_buf, 0, sizeof(key_buf));
00304                 MD5Update(&md5_ctx, key_buf, sizeof(key_buf) - data->mac_key.length);
00305         }
00306 #endif
00307 
00308         /* copy in the first bit of the SMB header */
00309         MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);
00310 
00311         /* copy in the sequence number, instead of the signature */
00312         MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));
00313 
00314         /* copy in the rest of the packet in, skipping the signature */
00315         MD5Update(&md5_ctx, buf + offset_end_of_sig, 
00316                   smb_len(buf) - (offset_end_of_sig - 4));
00317 
00318         /* calculate the MD5 sig */ 
00319         MD5Final(calc_md5_mac, &md5_ctx);
00320 }
00321 
00322 
00323 /***********************************************************
00324  SMB signing - Client implementation - send the MAC.
00325 ************************************************************/
00326 
00327 static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
00328 {
00329         unsigned char calc_md5_mac[16];
00330         struct smb_basic_signing_context *data =
00331                 (struct smb_basic_signing_context *)si->signing_context;
00332 
00333         if (!si->doing_signing)
00334                 return;
00335 
00336         /* JRA Paranioa test - we should be able to get rid of this... */
00337         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
00338                 DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n",
00339                                         smb_len(outbuf) ));
00340                 abort();
00341         }
00342 
00343         /* mark the packet as signed - BEFORE we sign it...*/
00344         mark_packet_signed(outbuf);
00345 
00346         simple_packet_signature(data, (const unsigned char *)outbuf,
00347                                 data->send_seq_num, calc_md5_mac);
00348 
00349         DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n"));
00350         dump_data(10, (const char *)calc_md5_mac, 8);
00351 
00352         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
00353 
00354 /*      cli->outbuf[smb_ss_field+2]=0; 
00355         Uncomment this to test if the remote server actually verifies signatures...*/
00356 
00357         /* Instead of re-introducing the trans_info_conect we
00358            used to have here, we use the fact that during a
00359            SMBtrans/SMBtrans2/SMBnttrans send that the mid stays
00360            constant. This means that calling store_sequence_for_reply()
00361            will return False for all trans secondaries, as the mid is already
00362            on the stored sequence list. As the send_seqence_number must
00363            remain constant for all primary+secondary trans sends, we
00364            only increment the send sequence number when we successfully
00365            add a new entry to the outstanding sequence list. This means
00366            I can isolate the fix here rather than re-adding the trans
00367            signing on/off calls in libsmb/clitrans2.c JRA.
00368          */
00369         
00370         if (store_sequence_for_reply(&data->outstanding_packet_list, SVAL(outbuf,smb_mid), data->send_seq_num + 1)) {
00371                 data->send_seq_num += 2;
00372         }
00373 }
00374 
00375 /***********************************************************
00376  SMB signing - Client implementation - check a MAC sent by server.
00377 ************************************************************/
00378 
00379 static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
00380 {
00381         BOOL good;
00382         uint32 reply_seq_number;
00383         unsigned char calc_md5_mac[16];
00384         unsigned char *server_sent_mac;
00385 
00386         struct smb_basic_signing_context *data =
00387                 (struct smb_basic_signing_context *)si->signing_context;
00388 
00389         if (!si->doing_signing)
00390                 return True;
00391 
00392         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
00393                 DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
00394                 return False;
00395         }
00396 
00397         if (!get_sequence_for_reply(&data->outstanding_packet_list, SVAL(inbuf, smb_mid), &reply_seq_number)) {
00398                 DEBUG(1, ("client_check_incoming_message: received message "
00399                         "with mid %u with no matching send record.\n", (unsigned int)SVAL(inbuf, smb_mid) ));
00400                 return False;
00401         }
00402 
00403         simple_packet_signature(data, (const unsigned char *)inbuf,
00404                                 reply_seq_number, calc_md5_mac);
00405 
00406         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
00407         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
00408         
00409         if (!good) {
00410                 DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n"));
00411                 dump_data(5, (const char *)calc_md5_mac, 8);
00412                 
00413                 DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n"));
00414                 dump_data(5, (const char *)server_sent_mac, 8);
00415 #if 1 /* JRATEST */
00416                 {
00417                         int i;
00418                         for (i = -5; i < 5; i++) {
00419                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number+i, calc_md5_mac);
00420                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
00421                                         DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches. \
00422 We were expecting seq %u\n", reply_seq_number+i, reply_seq_number ));
00423                                         break;
00424                                 }
00425                         }
00426                 }
00427 #endif /* JRATEST */
00428 
00429         } else {
00430                 DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
00431                 dump_data(10, (const char *)server_sent_mac, 8);
00432         }
00433         return signing_good(inbuf, si, good, reply_seq_number, must_be_ok);
00434 }
00435 
00436 /***********************************************************
00437  SMB signing - Simple implementation - free signing context
00438 ************************************************************/
00439 
00440 static void simple_free_signing_context(struct smb_sign_info *si)
00441 {
00442         struct smb_basic_signing_context *data =
00443                 (struct smb_basic_signing_context *)si->signing_context;
00444         struct outstanding_packet_lookup *list;
00445         struct outstanding_packet_lookup *next;
00446         
00447         for (list = data->outstanding_packet_list; list; list = next) {
00448                 next = list->next;
00449                 DLIST_REMOVE(data->outstanding_packet_list, list);
00450                 SAFE_FREE(list);
00451         }
00452 
00453         data_blob_free(&data->mac_key);
00454 
00455         SAFE_FREE(si->signing_context);
00456 
00457         return;
00458 }
00459 
00460 /***********************************************************
00461  SMB signing - Simple implementation - setup the MAC key.
00462 ************************************************************/
00463 
00464 BOOL cli_simple_set_signing(struct cli_state *cli,
00465                             const DATA_BLOB user_session_key,
00466                             const DATA_BLOB response)
00467 {
00468         struct smb_basic_signing_context *data;
00469 
00470         if (!user_session_key.length)
00471                 return False;
00472 
00473         if (!cli_set_smb_signing_common(cli)) {
00474                 return False;
00475         }
00476 
00477         if (!set_smb_signing_real_common(&cli->sign_info)) {
00478                 return False;
00479         }
00480 
00481         data = SMB_XMALLOC_P(struct smb_basic_signing_context);
00482         memset(data, '\0', sizeof(*data));
00483 
00484         cli->sign_info.signing_context = data;
00485         
00486         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
00487 
00488         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
00489 
00490         DEBUG(10, ("cli_simple_set_signing: user_session_key\n"));
00491         dump_data(10, (const char *)user_session_key.data, user_session_key.length);
00492 
00493         if (response.length) {
00494                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
00495                 DEBUG(10, ("cli_simple_set_signing: response_data\n"));
00496                 dump_data(10, (const char *)response.data, response.length);
00497         } else {
00498                 DEBUG(10, ("cli_simple_set_signing: NULL response_data\n"));
00499         }
00500 
00501         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
00502 
00503         /* Initialise the sequence number */
00504         data->send_seq_num = 0;
00505 
00506         /* Initialise the list of outstanding packets */
00507         data->outstanding_packet_list = NULL;
00508 
00509         cli->sign_info.sign_outgoing_message = client_sign_outgoing_message;
00510         cli->sign_info.check_incoming_message = client_check_incoming_message;
00511         cli->sign_info.free_signing_context = simple_free_signing_context;
00512 
00513         return True;
00514 }
00515 
00516 /***********************************************************
00517  SMB signing - TEMP implementation - calculate a MAC to send.
00518 ************************************************************/
00519 
00520 static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
00521 {
00522         /* mark the packet as signed - BEFORE we sign it...*/
00523         mark_packet_signed(outbuf);
00524 
00525         /* I wonder what BSRSPYL stands for - but this is what MS 
00526            actually sends! */
00527         memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
00528         return;
00529 }
00530 
00531 /***********************************************************
00532  SMB signing - TEMP implementation - check a MAC sent by server.
00533 ************************************************************/
00534 
00535 static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
00536 {
00537         return True;
00538 }
00539 
00540 /***********************************************************
00541  SMB signing - TEMP implementation - free signing context
00542 ************************************************************/
00543 
00544 static void temp_free_signing_context(struct smb_sign_info *si)
00545 {
00546         return;
00547 }
00548 
00549 /***********************************************************
00550  SMB signing - NULL implementation - setup the MAC key.
00551 ************************************************************/
00552 
00553 BOOL cli_null_set_signing(struct cli_state *cli)
00554 {
00555         return null_set_signing(&cli->sign_info);
00556 }
00557 
00558 /***********************************************************
00559  SMB signing - temp implementation - setup the MAC key.
00560 ************************************************************/
00561 
00562 BOOL cli_temp_set_signing(struct cli_state *cli)
00563 {
00564         if (!cli_set_smb_signing_common(cli)) {
00565                 return False;
00566         }
00567 
00568         cli->sign_info.signing_context = NULL;
00569         
00570         cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message;
00571         cli->sign_info.check_incoming_message = temp_check_incoming_message;
00572         cli->sign_info.free_signing_context = temp_free_signing_context;
00573 
00574         return True;
00575 }
00576 
00577 void cli_free_signing_context(struct cli_state *cli)
00578 {
00579         free_signing_context(&cli->sign_info);
00580 }
00581 
00582 /**
00583  * Sign a packet with the current mechanism
00584  */
00585  
00586 void cli_calculate_sign_mac(struct cli_state *cli)
00587 {
00588         cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
00589 }
00590 
00591 /**
00592  * Check a packet with the current mechanism
00593  * @return False if we had an established signing connection
00594  *         which had a bad checksum, True otherwise.
00595  */
00596  
00597 BOOL cli_check_sign_mac(struct cli_state *cli) 
00598 {
00599         if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, True)) {
00600                 free_signing_context(&cli->sign_info);  
00601                 return False;
00602         }
00603         return True;
00604 }
00605 
00606 /***********************************************************
00607  Enter trans/trans2/nttrans state.
00608 ************************************************************/
00609 
00610 BOOL client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid)
00611 {
00612         struct smb_sign_info *si = &cli->sign_info;
00613         struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context;
00614 
00615         if (!si->doing_signing) {
00616                 return True;
00617         }
00618 
00619         if (!data) {
00620                 return False;
00621         }
00622 
00623         if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, False)) {
00624                 return False;
00625         }
00626 
00627         return True;
00628 }
00629 
00630 /***********************************************************
00631  Leave trans/trans2/nttrans state.
00632 ************************************************************/
00633 
00634 BOOL client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid)
00635 {
00636         uint32 reply_seq_num;
00637         struct smb_sign_info *si = &cli->sign_info;
00638         struct smb_basic_signing_context *data = (struct smb_basic_signing_context *)si->signing_context;
00639 
00640         if (!si->doing_signing) {
00641                 return True;
00642         }
00643 
00644         if (!data) {
00645                 return False;
00646         }
00647 
00648         if (!set_sequence_can_delete_flag(&data->outstanding_packet_list, mid, True)) {
00649                 return False;
00650         }
00651 
00652         /* Now delete the stored mid entry. */
00653         if (!get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_num)) {
00654                 return False;
00655         }
00656 
00657         return True;
00658 }
00659 
00660 /***********************************************************
00661  SMB signing - Server implementation - send the MAC.
00662 ************************************************************/
00663 
00664 static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
00665 {
00666         unsigned char calc_md5_mac[16];
00667         struct smb_basic_signing_context *data =
00668                 (struct smb_basic_signing_context *)si->signing_context;
00669         uint32 send_seq_number = data->send_seq_num-1;
00670         uint16 mid;
00671 
00672         if (!si->doing_signing) {
00673                 return;
00674         }
00675 
00676         /* JRA Paranioa test - we should be able to get rid of this... */
00677         if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
00678                 DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
00679                                         smb_len(outbuf) ));
00680                 abort();
00681         }
00682 
00683         /* mark the packet as signed - BEFORE we sign it...*/
00684         mark_packet_signed(outbuf);
00685 
00686         mid = SVAL(outbuf, smb_mid);
00687 
00688         /* See if this is a reply for a deferred packet. */
00689         get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
00690 
00691         simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
00692 
00693         DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
00694         dump_data(10, (const char *)calc_md5_mac, 8);
00695 
00696         memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
00697 
00698 /*      cli->outbuf[smb_ss_field+2]=0; 
00699         Uncomment this to test if the remote client actually verifies signatures...*/
00700 }
00701 
00702 /***********************************************************
00703  SMB signing - Server implementation - check a MAC sent by server.
00704 ************************************************************/
00705 
00706 static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
00707 {
00708         BOOL good;
00709         struct smb_basic_signing_context *data =
00710                 (struct smb_basic_signing_context *)si->signing_context;
00711         uint32 reply_seq_number = data->send_seq_num;
00712         uint32 saved_seq;
00713         unsigned char calc_md5_mac[16];
00714         unsigned char *server_sent_mac;
00715 
00716         if (!si->doing_signing)
00717                 return True;
00718 
00719         if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
00720                 DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
00721                 return False;
00722         }
00723 
00724         /* We always increment the sequence number. */
00725         data->send_seq_num += 2;
00726 
00727         saved_seq = reply_seq_number;
00728         simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
00729 
00730         server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
00731         good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
00732         
00733         if (!good) {
00734 
00735                 if (saved_seq) {
00736                         DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
00737                                         (unsigned int)saved_seq));
00738                         dump_data(5, (const char *)calc_md5_mac, 8);
00739 
00740                         DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
00741                                                 (unsigned int)reply_seq_number));
00742                         dump_data(5, (const char *)server_sent_mac, 8);
00743                 }
00744                 
00745 #if 1 /* JRATEST */
00746                 {
00747                         int i;
00748                         reply_seq_number -= 5;
00749                         for (i = 0; i < 10; i++, reply_seq_number++) {
00750                                 simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
00751                                 if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
00752                                         DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
00753 We were expecting seq %u\n", reply_seq_number, saved_seq ));
00754                                         break;
00755                                 }
00756                         }
00757                 }
00758 #endif /* JRATEST */
00759 
00760         } else {
00761                 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));
00762                 dump_data(10, (const char *)server_sent_mac, 8);
00763         }
00764 
00765         return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
00766 }
00767 
00768 /***********************************************************
00769  SMB signing - server API's.
00770 ************************************************************/
00771 
00772 static struct smb_sign_info srv_sign_info = {
00773         null_sign_outgoing_message,
00774         null_check_incoming_message,
00775         null_free_signing_context,
00776         NULL,
00777         False,
00778         False,
00779         False,
00780         False
00781 };
00782 
00783 /***********************************************************
00784  Turn signing off or on for oplock break code.
00785 ************************************************************/
00786 
00787 BOOL srv_oplock_set_signing(BOOL onoff)
00788 {
00789         BOOL ret = srv_sign_info.doing_signing;
00790         srv_sign_info.doing_signing = onoff;
00791         return ret;
00792 }
00793 
00794 /***********************************************************
00795  Called to validate an incoming packet from the client.
00796 ************************************************************/
00797 
00798 BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
00799 {
00800         /* Check if it's a session keepalive. */
00801         if(CVAL(inbuf,0) == SMBkeepalive)
00802                 return True;
00803 
00804         return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
00805 }
00806 
00807 /***********************************************************
00808  Called to sign an outgoing packet to the client.
00809 ************************************************************/
00810 
00811 void srv_calculate_sign_mac(char *outbuf)
00812 {
00813         /* Check if it's a session keepalive. */
00814         /* JRA Paranioa test - do we ever generate these in the server ? */
00815         if(CVAL(outbuf,0) == SMBkeepalive)
00816                 return;
00817 
00818         srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
00819 }
00820 
00821 /***********************************************************
00822  Called by server to defer an outgoing packet.
00823 ************************************************************/
00824 
00825 void srv_defer_sign_response(uint16 mid)
00826 {
00827         struct smb_basic_signing_context *data;
00828 
00829         if (!srv_sign_info.doing_signing)
00830                 return;
00831 
00832         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
00833 
00834         if (!data)
00835                 return;
00836 
00837         /*
00838          * Ensure we only store this mid reply once...
00839          */
00840 
00841         store_sequence_for_reply(&data->outstanding_packet_list, mid,
00842                                  data->send_seq_num-1);
00843 }
00844 
00845 /***********************************************************
00846  Called to remove sequence records when a deferred packet is
00847  cancelled by mid. This should never find one....
00848 ************************************************************/
00849 
00850 void srv_cancel_sign_response(uint16 mid)
00851 {
00852         struct smb_basic_signing_context *data;
00853         uint32 dummy_seq;
00854 
00855         if (!srv_sign_info.doing_signing)
00856                 return;
00857 
00858         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
00859 
00860         if (!data)
00861                 return;
00862 
00863         DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
00864 
00865         while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
00866                 ;
00867 
00868         /* cancel doesn't send a reply so doesn't burn a sequence number. */
00869         data->send_seq_num -= 1;
00870 }
00871 
00872 /***********************************************************
00873  Called by server negprot when signing has been negotiated.
00874 ************************************************************/
00875 
00876 void srv_set_signing_negotiated(void)
00877 {
00878         srv_sign_info.allow_smb_signing = True;
00879         srv_sign_info.negotiated_smb_signing = True;
00880         if (lp_server_signing() == Required)
00881                 srv_sign_info.mandatory_signing = True;
00882 
00883         srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
00884         srv_sign_info.check_incoming_message = temp_check_incoming_message;
00885         srv_sign_info.free_signing_context = temp_free_signing_context;
00886 }
00887 
00888 /***********************************************************
00889  Returns whether signing is active. We can't use sendfile or raw
00890  reads/writes if it is.
00891 ************************************************************/
00892 
00893 BOOL srv_is_signing_active(void)
00894 {
00895         return srv_sign_info.doing_signing;
00896 }
00897 
00898 
00899 /***********************************************************
00900  Returns whether signing is negotiated. We can't use it unless it was
00901  in the negprot.  
00902 ************************************************************/
00903 
00904 BOOL srv_is_signing_negotiated(void)
00905 {
00906         return srv_sign_info.negotiated_smb_signing;
00907 }
00908 
00909 /***********************************************************
00910  Returns whether signing is actually happening
00911 ************************************************************/
00912 
00913 BOOL srv_signing_started(void)
00914 {
00915         struct smb_basic_signing_context *data;
00916 
00917         if (!srv_sign_info.doing_signing) {
00918                 return False;
00919         }
00920 
00921         data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
00922         if (!data)
00923                 return False;
00924 
00925         if (data->send_seq_num == 0) {
00926                 return False;
00927         }
00928 
00929         return True;
00930 }
00931 
00932 /***********************************************************
00933  Turn on signing from this packet onwards. 
00934 ************************************************************/
00935 
00936 void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
00937 {
00938         struct smb_basic_signing_context *data;
00939 
00940         if (!user_session_key.length)
00941                 return;
00942 
00943         if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
00944                 DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
00945                         (unsigned int)srv_sign_info.negotiated_smb_signing,
00946                         (unsigned int)srv_sign_info.mandatory_signing ));
00947                 return;
00948         }
00949 
00950         /* Once we've turned on, ignore any more sessionsetups. */
00951         if (srv_sign_info.doing_signing) {
00952                 return;
00953         }
00954         
00955         if (srv_sign_info.free_signing_context)
00956                 srv_sign_info.free_signing_context(&srv_sign_info);
00957         
00958         srv_sign_info.doing_signing = True;
00959 
00960         data = SMB_XMALLOC_P(struct smb_basic_signing_context);
00961         memset(data, '\0', sizeof(*data));
00962 
00963         srv_sign_info.signing_context = data;
00964         
00965         data->mac_key = data_blob(NULL, response.length + user_session_key.length);
00966 
00967         memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
00968         if (response.length)
00969                 memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
00970 
00971         dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
00972 
00973         DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
00974                                 BOOLSTR(srv_sign_info.negotiated_smb_signing),
00975                                 BOOLSTR(srv_sign_info.mandatory_signing) ));
00976 
00977         /* Initialise the sequence number */
00978         data->send_seq_num = 0;
00979 
00980         /* Initialise the list of outstanding packets */
00981         data->outstanding_packet_list = NULL;
00982 
00983         srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
00984         srv_sign_info.check_incoming_message = srv_check_incoming_message;
00985         srv_sign_info.free_signing_context = simple_free_signing_context;
00986 }

Sambaに対してSat Aug 29 21:23:06 2009に生成されました。  doxygen 1.4.7