Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

SMB.cc

Go to the documentation of this file.
00001 // $Id: SMB.cc,v 1.4 2005/09/08 22:29:07 kreibich Exp $
00002 //
00003 // Copyright (c) 1996-2004
00004 //      The Regents of the University of California.  All rights reserved.
00005 //
00006 // Redistribution and use in source and binary forms, with or without
00007 // modification, are permitted provided that: (1) source code distributions
00008 // retain the above copyright notice and this paragraph in its entirety, (2)
00009 // distributions including binary code include the above copyright notice and
00010 // this paragraph in its entirety in the documentation or other materials
00011 // provided with the distribution, and (3) all advertising materials mentioning
00012 // features or use of this software display the following acknowledgement:
00013 // ``This product includes software developed by the University of California,
00014 // Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
00015 // the University nor the names of its contributors may be used to endorse
00016 // or promote products derived from this software without specific prior
00017 // written permission.
00018 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
00019 // WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00020 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022 #include "NetVar.h"
00023 #include "SMB.h"
00024 #include "smb_pac.h"
00025 #include "Val.h"
00026 
00027 enum SMB_Command {
00028 #define SMB_COMMAND(name, value) name = value,
00029 #include "SMB_COM.def"
00030 #undef SMB_COMMAND
00031 };
00032 
00033 const char* SMB_command_name[256];
00034 StringVal* SMB_command_str[256];
00035 
00036 static void init_SMB_command_name()
00037         {
00038         static int initialized = 0;
00039         if ( initialized )
00040                 return;
00041 
00042         initialized = 1;
00043 
00044         for ( int i = 0; i < 256; ++i )
00045                 {
00046                 SMB_command_name[i] = "<unknown>";
00047                 SMB_command_str[i] = 0;
00048                 }
00049 
00050 #define SMB_COMMAND(name, value) SMB_command_name[value] = #name;
00051 #include "SMB_COM.def"
00052         }
00053 
00054 StringVal* get_SMB_command_str(int cmd)
00055         {
00056         if ( ! SMB_command_str[cmd] )
00057                 SMB_command_str[cmd] = new StringVal(SMB_command_name[cmd]);
00058 
00059         return SMB_command_str[cmd];
00060         }
00061 
00062 // ### TODO: the list of IPC pipes needs a lot of expansion
00063 static int lookup_IPC_name(BroString* name)
00064         {
00065         static const char* IPC_pipe_names[] = {
00066                 "\\locator", "\\epmapper", "\\samr", "\\lsarpc", 0
00067         };
00068 
00069         for ( int i = 0; IPC_pipe_names[i]; ++i )
00070                 {
00071                 if ( size_t(name->Len()) == strlen(IPC_pipe_names[i]) &&
00072                      strncmp((const char*) name->Bytes(),
00073                              IPC_pipe_names[i], name->Len()) == 0 )
00074                         return i + 1;
00075                 }
00076 
00077         return IPC_NONE;
00078         }
00079 
00080 SMB_Session::SMB_Session(Connection* c)
00081         {
00082         conn = c;
00083         dce_rpc_session = 0;
00084         init_SMB_command_name();
00085 
00086         // Strangely, one does not have to connect to IPC$ before
00087         // making DCE/RPC calls. So we assume that it's always IPC
00088         // unless confirmed otherwise.
00089         is_IPC = true;
00090         IPC_pipe = IPC_NONE;
00091 
00092         transaction_name = 0;
00093         transaction_subcmd = 0;
00094 
00095         andx(0) = andx(1) = 0;
00096         }
00097 
00098 SMB_Session::~SMB_Session()
00099         {
00100         Unref(transaction_name);
00101         delete dce_rpc_session;
00102         }
00103 
00104 void SMB_Session::Deliver(int is_orig, int len, const u_char* data)
00105         {
00106         if ( len == 0 )
00107                 return;
00108 
00109         try
00110                 {
00111                 const u_char *data_start = data;
00112                 const u_char *data_end = data + len;
00113                 BinPAC::SMB_header hdr;
00114                 int hdr_len = hdr.parse(data, data_end, 1);
00115                 data += hdr_len;
00116                 int next_command = hdr.command();
00117                 while ( data < data_end )
00118                         {
00119                         SMB_Body body(data, data_end);
00120                         andx(is_orig) = 0;
00121                         ParseMessage(is_orig, next_command, hdr, body);
00122                         int next = AndxOffset(is_orig, next_command);
00123                         if ( next <= 0 )
00124                                 break;
00125                         // Weird(fmt("ANDX! at %d", next));
00126                         if ( data_start + next < data + body.length() )
00127                                 {
00128                                 Weird(fmt("ANDX buffer overlapping: next = %d, buffer_end = %d", next, data + body.length() - data_start));
00129                                 break;
00130                                 }
00131                         data = data_start + next;
00132                         }
00133                 }
00134         catch ( const BinPAC::Exception& e )
00135                 {
00136                 conn->Weird(e.msg().c_str());
00137                 }
00138         }
00139 
00140 void SMB_Session::ParseMessage(int is_orig, int cmd,
00141                 BinPAC::SMB_header const &hdr, SMB_Body const &body)
00142         {
00143         if ( smb_message )
00144                 {
00145                 val_list* vl = new val_list;
00146                 StringVal* cmd_str = get_SMB_command_str(cmd);
00147                 Ref(cmd_str);
00148 
00149                 vl->append(conn->BuildConnVal());
00150                 vl->append(new Val(is_orig, TYPE_BOOL));
00151                 vl->append(cmd_str);
00152                 vl->append(new Val(body.length(), TYPE_COUNT));
00153 
00154                 conn->ConnectionEvent(smb_message, vl);
00155                 }
00156 
00157         if ( is_orig )
00158                 req_cmd = cmd;
00159 
00160         int ret = 0;
00161         switch ( cmd ) {
00162         case SMB_COM_TREE_CONNECT_ANDX:
00163                 if ( is_orig )
00164                         ret = ParseTreeConnectAndx(hdr, body);
00165                 else
00166                         ret = ParseAndx(is_orig, hdr, body);
00167                 break;
00168 
00169         case SMB_COM_NT_CREATE_ANDX:
00170                 if ( is_orig )
00171                         ret = ParseNtCreateAndx(hdr, body);
00172                 else
00173                         ret = ParseAndx(is_orig, hdr, body);
00174                 break;
00175 
00176         case SMB_COM_TRANSACTION:
00177         case SMB_COM_TRANSACTION2:
00178         case SMB_COM_TRANSACTION_SECONDARY:
00179         case SMB_COM_TRANSACTION2_SECONDARY:
00180                 ret = ParseTransaction(is_orig, cmd, hdr, body);
00181                 break;
00182 
00183         case SMB_COM_READ_ANDX:
00184                 if ( is_orig )
00185                         ret = ParseReadAndx(hdr, body);
00186                 else
00187                         ret = ParseReadAndxResponse(hdr, body);
00188                 break;
00189 
00190         case SMB_COM_WRITE_ANDX:
00191                 if ( is_orig )
00192                         ret = ParseWriteAndx(hdr, body);
00193                 else
00194                         ret = ParseWriteAndxResponse(hdr, body);
00195                 break;
00196 
00197         case SMB_COM_NEGOTIATE:
00198         case SMB_COM_CLOSE:
00199         case SMB_COM_TREE_DISCONNECT:
00200                 break;
00201 
00202         case SMB_COM_LOGOFF_ANDX:
00203         case SMB_COM_SESSION_SETUP_ANDX:
00204                 ret = ParseAndx(is_orig, hdr, body);
00205                 break;
00206 
00207         default:
00208                 Weird(fmt("unknown_SMB_command(0x%x)", cmd));
00209                 break;
00210         }
00211 
00212         if ( ret == -1 )
00213                 Weird("SMB_parsing_error");
00214         }
00215 
00216 int SMB_Session::ParseAndx(int is_orig,
00217                 BinPAC::SMB_header const &hdr, SMB_Body const &body)
00218         {
00219         BinPAC::SMB_generic_andx msg;
00220         msg.parse(body.data(), body.data() + body.length(), 1);
00221         if ( msg.word_count() > 0 )
00222                 andx(is_orig) = msg.andx();
00223         return 0;
00224         }
00225 
00226 int SMB_Session::ParseTreeConnectAndx(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00227         {
00228         BinPAC::SMB_tree_connect_andx req(hdr.unicode());
00229 
00230         req.parse(body.data(), body.data() + body.length(), 1);
00231         andx(1) = req.andx();
00232 
00233         BroString* path = ExtractString(req.path());
00234         BroString* service = ExtractString(req.service());
00235 
00236         // replicate path
00237         BroString* norm_path = new BroString(path->Bytes(), path->Len(), 1);
00238         norm_path->ToUpper();
00239 
00240         if ( strstr_n(norm_path->Len(), norm_path->Bytes(), 5,
00241                       (const u_char*) "\\IPC$") != -1 )
00242                 is_IPC = true;  // TODO: change is_IPC to 0 on tree_disconnect
00243         else
00244                 is_IPC = false;
00245 
00246         delete norm_path;
00247 
00248         if ( smb_com_tree_connect_andx )
00249                 {
00250                 val_list* vl = new val_list;
00251                 vl->append(conn->BuildConnVal());
00252                 vl->append(new StringVal(path));
00253                 vl->append(new StringVal(service));
00254                 conn->ConnectionEvent(smb_com_tree_connect_andx, vl);
00255                 }
00256         else
00257                 {
00258                 delete path;
00259                 delete service;
00260                 }
00261 
00262         return 0;
00263         }
00264 
00265 int SMB_Session::ParseNtCreateAndx(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00266         {
00267         BinPAC::SMB_nt_create_andx req(hdr.unicode());
00268 
00269         req.parse(body.data(), body.data() + body.length(), 1);
00270         andx(1) = req.andx();
00271 
00272         BroString* name = ExtractString(req.name());
00273 
00274         IPC_pipe = (enum IPC_named_pipe) lookup_IPC_name(name);
00275 
00276         if ( smb_com_nt_create_andx )
00277                 {
00278                 val_list* vl = new val_list;
00279                 vl->append(conn->BuildConnVal());
00280                 vl->append(new StringVal(name));
00281                 conn->ConnectionEvent(smb_com_nt_create_andx, vl);
00282                 }
00283         else
00284                 delete name;
00285 
00286         return 0;
00287         }
00288 
00289 int SMB_Session::ParseReadAndx(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00290         {
00291         BinPAC::SMB_read_andx req;
00292         req.parse(body.data(), body.data() + body.length(), 1);
00293         andx(1) = req.andx();
00294         return 0;
00295         }
00296 
00297 int SMB_Session::ParseReadAndxResponse(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00298         {
00299         BinPAC::SMB_read_andx_response resp;
00300 
00301         resp.parse(body.data(), body.data() + body.length(), 1);
00302         andx(0) = resp.andx();
00303 
00304         int data_count = resp.data_length();
00305         const u_char* data = resp.data().begin();
00306 
00307         if ( smb_com_read_andx )
00308                 {
00309                 val_list* vl = new val_list;
00310                 vl->append(conn->BuildConnVal());
00311                 vl->append(new StringVal(data_count, (const char*) data));
00312                 conn->ConnectionEvent(smb_com_read_andx, vl);
00313                 }
00314 
00315         CheckRPC(0, data_count, data);
00316         return 0;
00317         }
00318 
00319 int SMB_Session::ParseWriteAndx(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00320         {
00321         BinPAC::SMB_write_andx req;
00322         req.parse(body.data(), body.data() + body.length(), 1);
00323         andx(1) = req.andx();
00324 
00325         int data_count = req.data_length();
00326         const u_char* data = req.data().begin();
00327 
00328         if ( smb_com_write_andx )
00329                 {
00330                 val_list* vl = new val_list;
00331                 vl->append(conn->BuildConnVal());
00332                 vl->append(new StringVal(data_count, (const char*) data));
00333                 conn->ConnectionEvent(smb_com_write_andx, vl);
00334                 }
00335 
00336         CheckRPC(1, data_count, data);
00337         return 0;
00338         }
00339 
00340 int SMB_Session::ParseWriteAndxResponse(BinPAC::SMB_header const &hdr, SMB_Body const &body)
00341         {
00342         BinPAC::SMB_write_andx_response resp;
00343         resp.parse(body.data(), body.data() + body.length(), 1);
00344         andx(0) = resp.andx();
00345         return 0;
00346         }
00347 
00348 void SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
00349                                 int data_count, const u_char* data)
00350         {
00351         if ( f )
00352                 {
00353                 val_list* vl = new val_list;
00354 
00355                 vl->append(conn->BuildConnVal());
00356                 vl->append(new Val(is_orig, TYPE_BOOL));
00357                 vl->append(new Val(transaction_subcmd, TYPE_COUNT));
00358                 if ( transaction_name )
00359                         {
00360                         Ref(transaction_name);
00361                         vl->append(transaction_name);
00362                         }
00363                 else
00364                         vl->append(new StringVal(""));
00365                 vl->append(new StringVal(data_count, (const char*) data));
00366                 conn->ConnectionEvent(f, vl);
00367                 }
00368         }
00369 
00370 int SMB_Session::ParseTransaction(int is_orig, int cmd,
00371                 BinPAC::SMB_header const &hdr, SMB_Body const &body)
00372         {
00373         EventHandlerPtr f = 0;
00374         if ( cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION_SECONDARY )
00375                 f = smb_com_transaction;
00376         else if ( cmd == SMB_COM_TRANSACTION2 || cmd == SMB_COM_TRANSACTION2_SECONDARY )
00377                 f = smb_com_transaction2;
00378         else
00379                 internal_error("command mismatch for ParseTransaction");
00380 
00381         int ret;
00382         if ( is_orig )
00383                 {
00384                 if ( cmd == SMB_COM_TRANSACTION ||
00385                      cmd == SMB_COM_TRANSACTION2 )
00386                         ret = ParseTransactionRequest(cmd, hdr, body, f);
00387                 else if ( cmd == SMB_COM_TRANSACTION_SECONDARY ||
00388                           cmd == SMB_COM_TRANSACTION2_SECONDARY )
00389                         ret = ParseTransactionSecondaryRequest(cmd, hdr, body, f);
00390                 else
00391                         ret = 0;
00392                 }
00393         else
00394                 ret = ParseTransactionResponse(cmd, hdr, body, f);
00395 
00396         return ret;
00397         }
00398 
00399 int SMB_Session::ParseTransactionRequest(int cmd,
00400                 BinPAC::SMB_header const &hdr,
00401                 SMB_Body const &body,
00402                 EventHandlerPtr f)
00403         {
00404         BinPAC::SMB_transaction trans(
00405                 cmd == SMB_COM_TRANSACTION ? 1 : 2,
00406                 hdr.unicode());
00407         trans.parse(body.data(), body.data() + body.length(), 1);
00408 
00409         if ( transaction_name )
00410                 {
00411                 Unref(transaction_name);
00412                 transaction_name = 0;
00413                 }
00414 
00415         if ( cmd == SMB_COM_TRANSACTION )
00416                 transaction_name = new StringVal(
00417                         ExtractString(trans.name()));
00418 
00419         // TODO: LANMAN transaction uses the first u_short of
00420         // parameters as subcmd
00421         if ( trans.setup_count() > 0 )
00422                 transaction_subcmd = trans.setup()[0];
00423         else
00424                 Weird("transaction_subcmd_missing");
00425 
00426         TransactionEvent(f, true, trans.data_count(), trans.data().begin());
00427         return ProcessTransactionData(true, cmd, hdr,
00428                 trans.param_count(), trans.parameters().begin(),
00429                 trans.data_count(), trans.data().begin());
00430         }
00431 
00432 int SMB_Session::ParseTransactionSecondaryRequest(int cmd,
00433                 BinPAC::SMB_header const &hdr,
00434                 SMB_Body const &body,
00435                 EventHandlerPtr f)
00436         {
00437         BinPAC::SMB_transaction_secondary trans(hdr.unicode());
00438         trans.parse(body.data(), body.data() + body.length(), 1);
00439 
00440         TransactionEvent(f, true, trans.data_count(), trans.data().begin());
00441         return ProcessTransactionData(true, cmd, hdr,
00442                 trans.param_count(), trans.parameters().begin(),
00443                 trans.data_count(), trans.data().begin());
00444         }
00445 
00446 int SMB_Session::ParseTransactionResponse(int cmd,
00447                 BinPAC::SMB_header const &hdr,
00448                 SMB_Body const &body,
00449                 EventHandlerPtr f)
00450         {
00451         if ( body.word_count() == 0 ) // interim response
00452                 {
00453                 TransactionEvent(f, false, 0, 0);
00454                 return 0;
00455                 }
00456 
00457         BinPAC::SMB_transaction_response trans(hdr.unicode());
00458         trans.parse(body.data(), body.data() + body.length(), 1);
00459 
00460         TransactionEvent(f, false, trans.data_count(), trans.data().begin());
00461         return ProcessTransactionData(false, cmd, hdr,
00462                 trans.param_count(), trans.parameters().begin(),
00463                 trans.data_count(), trans.data().begin());
00464         }
00465 
00466 int SMB_Session::ProcessTransactionData(int is_orig, int cmd,
00467                 BinPAC::SMB_header const &hdr,
00468                 int param_count, const u_char* parameters,
00469                 int data_count, const u_char* data)
00470         {
00471         if ( cmd == SMB_COM_TRANSACTION )
00472                 {
00473                 switch ( transaction_subcmd ) {
00474                 case 0x26:
00475                         // Transact_named_pipe
00476                         break;
00477                 default:
00478                         if ( is_orig )
00479                                 Weird(fmt("unknown smb_transaction subcmd: 0x%x", transaction_subcmd));
00480                         break;
00481                 }
00482                 }
00483 
00484         int ret = 0;
00485         if ( cmd == SMB_COM_TRANSACTION2 )
00486                 {
00487                 switch ( transaction_subcmd ) {
00488                 case 0x5:
00489                         // QueryPathInfo
00490                         // TODO
00491                         break;
00492                 case 0x7:
00493                         // QueryFileInfo
00494                         // TODO
00495                         break;
00496                 case 0x10:
00497                         if ( is_orig )
00498                                 ret = ParseGetDFSReferral(hdr,
00499                                         param_count, parameters);
00500                         break;
00501 
00502                 default:
00503                         if ( is_orig )
00504                                 Weird(fmt("Unknown smb_transaction2 subcmd: 0x%x", transaction_subcmd));
00505                         break;
00506                 }
00507                 }
00508 
00509         if ( data_count > 0 )
00510                 {
00511                 if ( CheckRPC(is_orig, data_count, data) )
00512                         {
00513                         if ( cmd != SMB_COM_TRANSACTION ||
00514                              transaction_subcmd == 0x26 )
00515                                 Weird(fmt("RPC through unknown command: 0x%x/0x%x",
00516                                         cmd, transaction_subcmd));
00517                         }
00518                 }
00519 
00520         return ret;
00521         }
00522 
00523 int SMB_Session::ParseGetDFSReferral(BinPAC::SMB_header const &hdr,
00524                 int param_count, const u_char* param)
00525         {
00526         BinPAC::SMB_get_dfs_referral req(hdr.unicode());
00527         req.parse(param, param + param_count, 1);
00528 
00529         if ( smb_get_dfs_referral )
00530                 {
00531                 val_list* vl = new val_list;
00532                 vl->append(conn->BuildConnVal());
00533                 vl->append(new Val(req.max_referral_level(), TYPE_COUNT));
00534                 vl->append(new StringVal(ExtractString(req.file_name())));
00535                 conn->ConnectionEvent(smb_get_dfs_referral, vl);
00536                 }
00537 
00538         return 0;
00539         }
00540 
00541 int SMB_Session::AndxOffset(int is_orig, int& next_command) const
00542         {
00543         if ( ! andx(is_orig) )
00544                 return -1;
00545 
00546         next_command = andx(is_orig)->command();
00547         if ( next_command != 0xff )
00548                 return andx(is_orig)->offset();
00549         else
00550                 return -1;
00551         }
00552 
00553 void SMB_Session::Weird(const char* msg)
00554         {
00555         conn->Weird(msg);
00556         }
00557 
00558 // Extract a NUL-terminated string from [data, data+len-1]. The
00559 // input can be in Unicode (little endian), and the returned string
00560 // will be in ASCII.
00561 
00562 BroString* SMB_Session::ExtractString(BinPAC::SMB_string const* s)
00563         {
00564         return s->unicode() ? ExtractString(s->u()) : ExtractString(s->a());
00565         }
00566 
00567 BroString* SMB_Session::ExtractString(BinPAC::SMB_ascii_string const* s)
00568         {
00569         return new BroString(s->val().begin(), s->val().size(), 1);
00570         }
00571 
00572 BroString* SMB_Session::ExtractString(BinPAC::SMB_unicode_string const* s)
00573         {
00574         u_char* b = new u_char[s->s().size() + 1];
00575         int i;
00576         for ( i = 0; i < s->s().size(); ++i )
00577                 {
00578                 uint16 x = s->s()[i];
00579                 if ( x & 0xff00 )
00580                         Weird(fmt("unicode string confusion: 0x%04x", x));
00581                 b[i] = u_char(x & 0xff);
00582                 }
00583         b[i] = 0;
00584         return new BroString(1, b, s->s().size());
00585         }
00586 
00587 bool SMB_Session::LooksLikeRPC(int len, const u_char* msg)
00588         {
00589         // DEBUG_MSG("is_IPC = %d, IPC_pipe = %d\n", is_IPC, IPC_pipe);
00590         // if ( ! is_IPC )
00591         //      return false;
00592 
00593         try
00594                 {
00595                 BinPAC::DCE_RPC_Header h;
00596                 h.parse(msg, msg + len, 0);
00597                 if ( h.rpc_vers() == 5 && h.rpc_vers_minor() == 0 )
00598                         {
00599                         if ( h.frag_length() == len )
00600                                 return true;
00601                         else
00602                                 {
00603                                 DEBUG_MSG("length mismatch: %d != %d\n",
00604                                         h.frag_length(), len);
00605                                 return false;
00606                                 }
00607                         }
00608                 }
00609         catch ( const BinPAC::Exception& )
00610                 {
00611                 // do nothing
00612                 }
00613 
00614         return false;
00615         }
00616 
00617 bool SMB_Session::CheckRPC(int is_orig, int data_count, const u_char *data)
00618         {
00619         if ( LooksLikeRPC(data_count, data) )
00620                 {
00621                 if ( ! dce_rpc_session )
00622                         dce_rpc_session = new DCE_RPC_Session(conn);
00623 
00624                 dce_rpc_session->DeliverPDU(is_orig, data_count, data);
00625                 return true;
00626                 }
00627         return false;
00628         }
00629 
00630 TCP_Contents_SMB::TCP_Contents_SMB(TCP_Endpoint* arg_endp, SMB_Session* s)
00631 : TCP_Contents(arg_endp, STOP_ON_GAP, PUNT_ON_PARTIAL)
00632         {
00633         smb_session = s;
00634         msg_buf = 0;
00635         msg_len = 0;
00636         buf_len = 0;
00637         buf_n = 0;
00638         }
00639 
00640 void TCP_Contents_SMB::InitMsgBuf()
00641         {
00642         delete [] msg_buf;
00643         msg_buf = new u_char[msg_len];
00644         buf_len = msg_len;
00645         buf_n = 0;
00646         }
00647 
00648 TCP_Contents_SMB::~TCP_Contents_SMB()
00649         {
00650         delete [] msg_buf;
00651         }
00652 
00653 void TCP_Contents_SMB::DeliverSMB(int len, const u_char* data)
00654         {
00655         // Check the 4-byte header.
00656         if ( strncmp((const char*) data, "\xffSMB", 4) )
00657                 {
00658                 Conn()->Weird(fmt("SMB-over-TCP header error: %02x%02x%02x%02x, \\x%02x%c%c%c",
00659                         dshdr[0], dshdr[1], dshdr[2], dshdr[3],
00660                         data[0], data[1], data[2], data[3]));
00661                 SetSkipDeliveries(1);
00662                 }
00663         else
00664                 smb_session->Deliver(IsOrig(), len, data);
00665 
00666         buf_n = 0;
00667         msg_len = 0;
00668         }
00669 
00670 void TCP_Contents_SMB::Deliver(int /* seq */, int len, const u_char* data)
00671         {
00672         while ( len > 0 )
00673                 {
00674                 if ( ! msg_len )
00675                         {
00676                         // Get the SMB-over-TCP header (4 bytes).
00677                         while ( buf_n < 4 && len > 0 )
00678                                 {
00679                                 dshdr[buf_n] = *data;
00680                                 ++buf_n; ++data; --len;
00681                                 }
00682 
00683                         if ( buf_n < 4 )
00684                                 return;
00685 
00686                         buf_n = 0;
00687                         for ( int i = 1; i < 4; ++i )
00688                                 msg_len = ( msg_len << 8 ) + dshdr[i];
00689 
00690                         if ( dshdr[0] != 0 || msg_len <= 4 )
00691                                 {
00692                                 Conn()->Weird("SMB message length error");
00693                                 SetSkipDeliveries(1);
00694                                 return;
00695                                 }
00696                         }
00697 
00698                 if ( buf_n == 0 && msg_len <= len )
00699                         {
00700                         // The fast lane:
00701                         // Keep msg_len -- it will be changed in DeliverSMB
00702                         int mlen = msg_len;
00703                         DeliverSMB(msg_len, data);
00704                         len -= mlen;
00705                         data += mlen;
00706                         }
00707 
00708                 else
00709                         {
00710                         if ( buf_len < msg_len )
00711                                 InitMsgBuf();
00712 
00713                         while ( buf_n < msg_len && len > 0 )
00714                                 {
00715                                 msg_buf[buf_n] = *data;
00716                                 ++buf_n;
00717                                 ++data;
00718                                 --len;
00719                                 }
00720 
00721                         if ( buf_n < msg_len )
00722                                 return;
00723 
00724                         DeliverSMB(msg_len, msg_buf);
00725                         }
00726                 }
00727         }
00728 
00729 SMB_TCP_Conn::SMB_TCP_Conn(NetSessions* s, HashKey* k, double t,
00730                                 const ConnID* id, const struct tcphdr* tp)
00731 :TCP_Connection(s, k, t, id, tp)
00732         {
00733         o_smb = r_smb = 0;
00734         smb_session = new SMB_Session(this);
00735         }
00736 
00737 SMB_TCP_Conn::~SMB_TCP_Conn()
00738         {
00739         delete smb_session;
00740         }
00741 
00742 void SMB_TCP_Conn::BuildEndpoints()
00743         {
00744         o_smb = new TCP_Contents_SMB(orig, smb_session);
00745         r_smb = new TCP_Contents_SMB(resp, smb_session);
00746 
00747         orig->AddContentsProcessor(o_smb);
00748         resp->AddContentsProcessor(r_smb);
00749         }

Generated on Wed Sep 14 02:56:51 2005 for bro_docs by doxygen 1.3.5