LCOV - code coverage report
Current view: top level - src - SMB.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 567 0.4 %
Date: 2010-12-13 Functions: 2 58 3.4 %
Branches: 2 309 0.6 %

           Branch data     Line data    Source code
       1                 :            : // $Id: SMB.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "NetVar.h"
       6                 :            : #include "SMB.h"
       7                 :            : #include "smb_pac.h"
       8                 :            : #include "Val.h"
       9                 :            : 
      10                 :            : namespace {
      11                 :            :         const bool DEBUG_smb_ipc = true;
      12                 :            : }
      13                 :            : 
      14                 :            : #define BYTEORDER_SWAP16(n) ((256 * ((n) & 0xff)) + ((n) >> 8))
      15                 :            : 
      16                 :            : enum SMB_Command {
      17                 :            : #define SMB_COMMAND(name, value) name = value,
      18                 :            : #include "SMB_COM.def"
      19                 :            : #undef SMB_COMMAND
      20                 :            : };
      21                 :            : 
      22                 :            : enum SMB_Transaction_Command {
      23                 :            :         HOST_ANNOUNCEMENT = 1,
      24                 :            :         ANNOUCEMENT_REQUEST = 2,
      25                 :            :         REQUEST_ELECTION = 8,
      26                 :            :         GET_BACKUP_LIST_REQUEST = 9,
      27                 :            :         GET_BACKUP_LIST_RESPONSE = 10,
      28                 :            :         BECOME_BACKUP_REQUEST = 11,
      29                 :            :         DOMAIN_ANNOUNCEMENT = 12,
      30                 :            :         MASTER_ANNOUNCEMENT = 13,
      31                 :            :         RESET_BROWSER_STATE = 14,
      32                 :            :         LOCAL_MASTER_ANNOUNCEMENT = 15,
      33                 :            : };
      34                 :            : 
      35                 :            : const char* SMB_command_name[256];
      36                 :            : StringVal* SMB_command_str[256];
      37                 :            : const char* SMB_trans_command_name[256];
      38                 :            : StringVal* SMB_trans_command_str[256];
      39                 :            : 
      40                 :          0 : static void init_SMB_command_name()
      41                 :            :         {
      42                 :            :         static int initialized = 0;
      43         [ #  # ]:          0 :         if ( initialized )
      44                 :          0 :                 return;
      45                 :            : 
      46                 :          0 :         initialized = 1;
      47                 :            : 
      48         [ #  # ]:          0 :         for ( int i = 0; i < 256; ++i )
      49                 :            :                 {
      50                 :          0 :                 SMB_command_name[i] = "<unknown>";
      51                 :          0 :                 SMB_command_str[i] = 0;
      52                 :            :                 }
      53                 :            : 
      54                 :            : #define SMB_COMMAND(name, value) SMB_command_name[value] = #name;
      55                 :            : #include "SMB_COM.def"
      56                 :            : #undef SMB_COMMAND
      57                 :            : #define SMB_COMMAND(name, value) SMB_trans_command_name[value] = #name;
      58                 :          0 :         SMB_COMMAND(HOST_ANNOUNCEMENT, 1)
      59                 :          0 :         SMB_COMMAND(ANNOUCEMENT_REQUEST, 2)
      60                 :          0 :         SMB_COMMAND(REQUEST_ELECTION, 8)
      61                 :          0 :         SMB_COMMAND(GET_BACKUP_LIST_REQUEST, 9)
      62                 :          0 :         SMB_COMMAND(GET_BACKUP_LIST_RESPONSE, 10)
      63                 :          0 :         SMB_COMMAND(BECOME_BACKUP_REQUEST, 11)
      64                 :          0 :         SMB_COMMAND(DOMAIN_ANNOUNCEMENT, 12)
      65                 :          0 :         SMB_COMMAND(MASTER_ANNOUNCEMENT, 13)
      66                 :          0 :         SMB_COMMAND(RESET_BROWSER_STATE, 14)
      67                 :          0 :         SMB_COMMAND(LOCAL_MASTER_ANNOUNCEMENT, 15)
      68                 :            : 
      69                 :            :         }
      70                 :            : 
      71                 :          0 : StringVal* get_SMB_command_str(int cmd)
      72                 :            :         {
      73         [ #  # ]:          0 :         if ( ! SMB_command_str[cmd] )
      74                 :          0 :                 SMB_command_str[cmd] = new StringVal(SMB_command_name[cmd]);
      75                 :            : 
      76                 :          0 :         return SMB_command_str[cmd];
      77                 :            :         }
      78                 :            : 
      79                 :            : // ### TODO: the list of IPC pipes needs a lot of expansion.
      80                 :          0 : static int lookup_IPC_name(BroString* name)
      81                 :            :         {
      82                 :            :         static const char* IPC_pipe_names[] = {
      83                 :            :                 "\\locator", "\\epmapper", "\\samr", "\\lsarpc", 0
      84                 :            :         };
      85                 :            : 
      86         [ #  # ]:          0 :         for ( int i = 0; IPC_pipe_names[i]; ++i )
      87                 :            :                 {
      88 [ #  # ][ #  # ]:          0 :                 if ( size_t(name->Len()) == strlen(IPC_pipe_names[i]) &&
                 [ #  # ]
      89                 :            :                      strncmp((const char*) name->Bytes(),
      90                 :            :                              IPC_pipe_names[i], name->Len()) == 0 )
      91                 :          0 :                         return i + 1;
      92                 :            :                 }
      93                 :            : 
      94                 :          0 :         return IPC_NONE;
      95                 :            :         }
      96                 :            : 
      97                 :          0 : SMB_Session::SMB_Session(Analyzer* arg_analyzer)
      98                 :            :         {
      99                 :          0 :         analyzer = arg_analyzer;
     100                 :          0 :         dce_rpc_session = 0;
     101                 :          0 :         init_SMB_command_name();
     102                 :            : 
     103                 :            :         // Strangely, one does not have to connect to IPC$ before
     104                 :            :         // making DCE/RPC calls. So we assume that it's always IPC
     105                 :            :         // unless confirmed otherwise.
     106                 :            : 
     107                 :          0 :         is_IPC = true;
     108                 :          0 :         IPC_pipe = IPC_NONE;
     109                 :            : 
     110                 :          0 :         transaction_name = 0;
     111                 :          0 :         transaction_subcmd = 0;
     112                 :            : 
     113                 :          0 :         andx_[0] = andx_[1] = 0;
     114                 :          0 :         set_andx(0, 0);
     115                 :          0 :         set_andx(1, 0);
     116                 :            : 
     117                 :          0 :         }
     118                 :            : 
     119                 :          0 : SMB_Session::~SMB_Session()
     120                 :            :         {
     121                 :          0 :         binpac::Unref(andx_[0]);
     122                 :          0 :         binpac::Unref(andx_[1]);
     123                 :          0 :         Unref(transaction_name);
     124   [ #  #  #  # ]:          0 :         delete dce_rpc_session;
     125                 :          0 :         }
     126                 :            : 
     127                 :          0 : void SMB_Session::set_andx(int is_orig, binpac::SMB::SMB_andx* andx)
     128                 :            :         {
     129         [ #  # ]:          0 :         int ind = is_orig ? 1 : 0;
     130         [ #  # ]:          0 :         if ( andx )
     131                 :          0 :                 andx->Ref();
     132                 :            : 
     133                 :          0 :         binpac::Unref(andx_[ind]);
     134                 :            : 
     135                 :          0 :         andx_[ind] = andx;
     136                 :          0 :         }
     137                 :            : 
     138                 :          0 : void SMB_Session::Deliver(int is_orig, int len, const u_char* data)
     139                 :            :         {
     140         [ #  # ]:          0 :         if ( len == 0 )
     141                 :          0 :                 return;
     142                 :            : 
     143                 :            :         try
     144                 :            :                 {
     145                 :          0 :                 const u_char* data_start = data;
     146                 :          0 :                 const u_char* data_end = data + len;
     147                 :            : 
     148                 :          0 :                 binpac::SMB::SMB_header hdr;
     149                 :          0 :                 int hdr_len = hdr.Parse(data, data_end);
     150                 :            : 
     151                 :          0 :                 data += hdr_len;
     152                 :            : 
     153                 :          0 :                 int next_command = hdr.command();
     154                 :            : 
     155 [ #  # ][ #  # ]:          0 :                 while ( data < data_end )
     156                 :            :                         {
     157                 :          0 :                         SMB_Body body(data, data_end);
     158                 :          0 :                         set_andx(is_orig, 0);
     159                 :          0 :                         ParseMessage(is_orig, next_command, hdr, body);
     160                 :            : 
     161                 :          0 :                         int next = AndxOffset(is_orig, next_command);
     162         [ #  # ]:          0 :                         if ( next <= 0 )
     163                 :          0 :                                 break;
     164                 :            : 
     165                 :            :                         //Weird(fmt("ANDX! at %d", next));
     166                 :          0 :                         const u_char* tmp = data_start + next;
     167         [ #  # ]:          0 :                         if ( data_start + next < data + body.length() )
     168                 :            :                                 {
     169                 :          0 :                                 Weird(fmt("ANDX buffer overlapping: next = %d, buffer_end = %d", next, data + body.length() - data_start));
     170                 :            :                                 break;
     171                 :            :                                 }
     172                 :            : 
     173                 :          0 :                         data = data_start + next;
     174                 :          0 :                         }
     175                 :            :                 }
     176                 :          0 :         catch ( const binpac::Exception& e )
     177                 :            :                 {
     178                 :          0 :                 analyzer->Weird(e.msg().c_str());
     179                 :            :                 }
     180                 :            :         }
     181                 :            : 
     182                 :            : void SMB_Session::ParseMessage(int is_orig, int cmd,
     183                 :            :                                 binpac::SMB::SMB_header const& hdr,
     184                 :          0 :                                 SMB_Body const& body)
     185                 :            :         {
     186         [ #  # ]:          0 :         if ( smb_message )
     187                 :            :                 {
     188                 :          0 :                 val_list* vl = new val_list;
     189                 :          0 :                 StringVal* cmd_str = get_SMB_command_str(cmd);
     190                 :          0 :                 Ref(cmd_str);
     191                 :            : 
     192                 :          0 :                 vl->append(analyzer->BuildConnVal());
     193                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     194                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
     195                 :          0 :                 vl->append(cmd_str);
     196                 :          0 :                 vl->append(new Val(body.length(), TYPE_COUNT));
     197                 :            :                 vl->append(new StringVal(body.length(),
     198                 :          0 :                                         (const char*) body.data()));
     199                 :            : 
     200                 :          0 :                 analyzer->ConnectionEvent(smb_message, vl);
     201                 :            :                 }
     202                 :            : 
     203         [ #  # ]:          0 :         if ( is_orig )
     204                 :          0 :                 req_cmd = cmd;
     205                 :            : 
     206                 :            :         // What if there's an error?
     207                 :            :         // if ( hdr.status->status() || hdr.status->dos_error() )
     208                 :            :         // The command code in the header might be right, but
     209                 :            :         // the response is probably mangled :-(.
     210                 :            : 
     211                 :          0 :         int ci = hdr.status()->val_case_index();
     212   [ #  #  #  # ]:          0 :         if ( (ci == 1 && hdr.status()->status()) ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     213                 :            :              (ci == 0 && (hdr.status()->dos_error()->error_class() ||
     214                 :            :                           hdr.status()->dos_error()->error())) )
     215                 :            :                 {
     216                 :          0 :                 unsigned int error = 0;
     217                 :            : 
     218      [ #  #  # ]:          0 :                 switch ( ci ) {
     219                 :            :                 case 0:
     220                 :            :                         error = hdr.status()->dos_error()->error_class() << 24 ||
     221 [ #  # ][ #  # ]:          0 :                                 hdr.status()->dos_error()->error();
     222                 :          0 :                         break;
     223                 :            :                 case 1:
     224                 :          0 :                         error = hdr.status()->status();
     225                 :            :                         break;
     226                 :            :                 }
     227                 :            : 
     228                 :          0 :                 val_list* vl = new val_list;
     229                 :          0 :                 StringVal* cmd_str = get_SMB_command_str(cmd);
     230                 :          0 :                 Ref(cmd_str);
     231                 :            : 
     232                 :          0 :                 vl->append(analyzer->BuildConnVal());
     233                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     234                 :          0 :                 vl->append(new Val(cmd, TYPE_COUNT));
     235                 :          0 :                 vl->append(cmd_str);
     236                 :            :                 vl->append(new StringVal(body.length(),
     237                 :          0 :                                         (const char*) body.data()));
     238                 :            : 
     239                 :          0 :                 analyzer->ConnectionEvent(smb_error, vl);
     240                 :            : 
     241                 :            :                 // Is this the right behavior?
     242                 :          0 :                 return;
     243                 :            :                 }
     244                 :            : 
     245                 :          0 :         int ret = 0;
     246 [ #  #  #  #  # :          0 :         switch ( cmd ) {
          #  #  #  #  #  
                      # ]
     247                 :            :         case SMB_COM_TREE_CONNECT_ANDX:
     248         [ #  # ]:          0 :                 if ( is_orig )
     249                 :          0 :                         ret = ParseTreeConnectAndx(hdr, body);
     250                 :            :                 else
     251                 :          0 :                         ret = ParseAndx(is_orig, hdr, body);
     252                 :          0 :                 break;
     253                 :            : 
     254                 :            :         case SMB_COM_NT_CREATE_ANDX:
     255         [ #  # ]:          0 :                 if ( is_orig )
     256                 :          0 :                         ret = ParseNtCreateAndx(hdr, body);
     257                 :            :                 else
     258                 :          0 :                         ret = ParseAndx(is_orig, hdr, body);
     259                 :          0 :                 break;
     260                 :            : 
     261                 :            :         case SMB_COM_TRANSACTION:
     262                 :            :         case SMB_COM_TRANSACTION2:
     263                 :            :         case SMB_COM_TRANSACTION_SECONDARY:
     264                 :            :         case SMB_COM_TRANSACTION2_SECONDARY:
     265                 :          0 :                 ret = ParseTransaction(is_orig, cmd, hdr, body);
     266                 :          0 :                 break;
     267                 :            : 
     268                 :            :         case SMB_COM_READ_ANDX:
     269         [ #  # ]:          0 :                 if ( is_orig )
     270                 :          0 :                         ret = ParseReadAndx(hdr, body);
     271                 :            :                 else
     272                 :          0 :                         ret = ParseReadAndxResponse(hdr, body);
     273                 :          0 :                 break;
     274                 :            : 
     275                 :            :         case SMB_COM_WRITE_ANDX:
     276         [ #  # ]:          0 :                 if ( is_orig )
     277                 :          0 :                         ret = ParseWriteAndx(hdr, body);
     278                 :            :                 else
     279                 :          0 :                         ret = ParseWriteAndxResponse(hdr, body);
     280                 :          0 :                 break;
     281                 :            : 
     282                 :            :         case SMB_COM_NEGOTIATE:
     283         [ #  # ]:          0 :                 if ( is_orig )
     284                 :          0 :                         ret = ParseNegotiate(hdr, body);
     285                 :            :                 else
     286                 :          0 :                         ret = ParseNegotiateResponse(hdr, body);
     287                 :          0 :                 break;
     288                 :            : 
     289                 :            :         case SMB_COM_CLOSE:
     290                 :          0 :                 ret = ParseClose(is_orig, hdr, body);
     291                 :          0 :                 break;
     292                 :            : 
     293                 :            :         case SMB_COM_TREE_DISCONNECT:
     294                 :          0 :                 ret = ParseTreeDisconnect(is_orig, hdr, body);
     295                 :          0 :                 break;
     296                 :            : 
     297                 :            :         case SMB_COM_LOGOFF_ANDX:
     298         [ #  # ]:          0 :                 if ( is_orig )
     299                 :          0 :                         ret = ParseLogoffAndx(is_orig, hdr, body);
     300                 :            :                 else
     301                 :          0 :                         ret = ParseAndx(is_orig, hdr, body);
     302                 :          0 :                 break;
     303                 :            : 
     304                 :            :         case SMB_COM_SESSION_SETUP_ANDX:
     305         [ #  # ]:          0 :                 if ( is_orig )
     306                 :          0 :                         ret = ParseSetupAndx(is_orig, hdr, body);
     307                 :            :                 else
     308                 :          0 :                         ret = ParseAndx(is_orig, hdr, body);
     309                 :          0 :                 break;
     310                 :            : 
     311                 :            :         default:
     312                 :          0 :                 Weird(fmt("unknown_SMB_command(0x%x)", cmd));
     313                 :            :                 break;
     314                 :            :         }
     315                 :            : 
     316         [ #  # ]:          0 :         if ( ret == -1 )
     317                 :          0 :                 Weird("SMB_parsing_error");
     318                 :            :         }
     319                 :            : 
     320                 :            : int SMB_Session::ParseNegotiate(binpac::SMB::SMB_header const& hdr,
     321                 :          0 :                                 SMB_Body const& body)
     322                 :            :         {
     323                 :          0 :         binpac::SMB::SMB_negotiate msg;
     324                 :          0 :         msg.Parse(body.data(), body.data() + body.length());
     325                 :            : 
     326         [ #  # ]:          0 :         if ( smb_com_negotiate )
     327                 :            :                 {
     328                 :          0 :                 TableVal* t = new TableVal(smb_negotiate);
     329         [ #  # ]:          0 :                 for ( int i = 0; i < int(msg.dialects()->size()); ++i )
     330                 :            :                         {
     331                 :          0 :                         binpac::SMB::SMB_dialect* d = (*msg.dialects())[i];
     332                 :          0 :                         BroString* tmp = ExtractString(d->dialectname());
     333                 :          0 :                         t->Assign(new Val(i, TYPE_COUNT), new StringVal(tmp));
     334                 :            :                         }
     335                 :            : 
     336                 :          0 :                 val_list* vl = new val_list;
     337                 :          0 :                 vl->append(analyzer->BuildConnVal());
     338                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     339                 :          0 :                 vl->append(t);
     340                 :            : 
     341                 :          0 :                 analyzer->ConnectionEvent(smb_com_negotiate, vl);
     342                 :            :                 }
     343                 :            : 
     344                 :          0 :         return 0;
     345                 :            :         }
     346                 :            : 
     347                 :            : int SMB_Session::ParseNegotiateResponse(binpac::SMB::SMB_header const& hdr,
     348                 :          0 :                                         SMB_Body const& body)
     349                 :            :         {
     350                 :          0 :         binpac::SMB::SMB_negotiate_response msg;
     351                 :          0 :         msg.Parse(body.data(), body.data() + body.length());
     352                 :            : 
     353         [ #  # ]:          0 :         if ( smb_com_negotiate_response )
     354                 :            :                 {
     355                 :          0 :                 val_list* vl = new val_list;
     356                 :          0 :                 vl->append(analyzer->BuildConnVal());
     357                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     358                 :          0 :                 vl->append(new Val(msg.dialect_index(), TYPE_COUNT));
     359                 :            : 
     360                 :          0 :                 analyzer->ConnectionEvent(smb_com_negotiate_response, vl);
     361                 :            :                 }
     362                 :            : 
     363                 :          0 :         return 0;
     364                 :            :         }
     365                 :            : 
     366                 :            : int SMB_Session::ParseSetupAndx(int is_orig, binpac::SMB::SMB_header const& hdr,
     367                 :          0 :                                 SMB_Body const& body)
     368                 :            :         {
     369                 :            :         // The binpac type depends on the negotiated server settings -
     370                 :            :         // possibly we can just pick the "right" format here, and use that?
     371                 :            : 
     372 [ #  # ][ #  # ]:          0 :         if ( hdr.flags2() && 0x0800 )
     373                 :            :                 {
     374                 :          0 :                 binpac::SMB::SMB_setup_andx_ext msg(hdr.unicode());
     375                 :          0 :                 msg.Parse(body.data(), body.data() + body.length());
     376                 :          0 :                 set_andx(1, msg.andx());
     377                 :            :                 }
     378                 :            :         else
     379                 :            :                 {
     380                 :          0 :                 binpac::SMB::SMB_setup_andx_basic msg(hdr.unicode());
     381                 :          0 :                 msg.Parse(body.data(), body.data() + body.length());
     382                 :          0 :                 set_andx(1, msg.andx());
     383                 :            :                 }
     384                 :            : 
     385         [ #  # ]:          0 :         if ( smb_com_setup_andx )
     386                 :            :                 {
     387                 :          0 :                 val_list* vl = new val_list;
     388                 :          0 :                 vl->append(analyzer->BuildConnVal());
     389                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     390                 :            : 
     391                 :          0 :                 analyzer->ConnectionEvent(smb_com_setup_andx, vl);
     392                 :            :                 }
     393                 :            : 
     394                 :          0 :         return 0;
     395                 :            :         }
     396                 :            : 
     397                 :            : int SMB_Session::ParseClose(int is_orig, binpac::SMB::SMB_header const& hdr,
     398                 :          0 :                                 SMB_Body const& body)
     399                 :            :         {
     400         [ #  # ]:          0 :         if ( smb_com_close )
     401                 :            :                 {
     402                 :          0 :                 val_list* vl = new val_list;
     403                 :          0 :                 vl->append(analyzer->BuildConnVal());
     404                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     405                 :            : 
     406                 :          0 :                 analyzer->ConnectionEvent(smb_com_close, vl);
     407                 :            :                 }
     408                 :            : 
     409                 :          0 :         return 0;
     410                 :            :         }
     411                 :            : 
     412                 :            : int SMB_Session::ParseLogoffAndx(int is_orig,
     413                 :            :                                         binpac::SMB::SMB_header const& hdr,
     414                 :          0 :                                         SMB_Body const& body)
     415                 :            :         {
     416                 :          0 :         binpac::SMB::SMB_generic_andx msg;
     417                 :          0 :         msg.Parse(body.data(), body.data() + body.length());
     418         [ #  # ]:          0 :         if ( msg.word_count() > 0 )
     419                 :          0 :                 set_andx(is_orig, msg.andx());
     420                 :            : 
     421         [ #  # ]:          0 :         if ( smb_com_logoff_andx )
     422                 :            :                 {
     423                 :          0 :                 val_list* vl = new val_list;
     424                 :          0 :                 vl->append(analyzer->BuildConnVal());
     425                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     426                 :            : 
     427                 :          0 :                 analyzer->ConnectionEvent(smb_com_logoff_andx, vl);
     428                 :            :                 }
     429                 :            : 
     430                 :          0 :         return 0;
     431                 :            :         }
     432                 :            :  
     433                 :            : int SMB_Session::ParseAndx(int is_orig, binpac::SMB::SMB_header const& hdr,
     434                 :          0 :                                 SMB_Body const& body)
     435                 :            :         {
     436                 :            :         // This is a generic ANDX event generator.  It passes the header
     437                 :            :         // and the ANDX data out to the policy.
     438                 :            :         try
     439                 :            :                 {
     440                 :          0 :                 binpac::SMB::SMB_generic_andx msg;
     441                 :          0 :                 msg.Parse(body.data(), body.data() + body.length());
     442         [ #  # ]:          0 :                 if ( msg.word_count() > 0 )
     443                 :          0 :                         set_andx(is_orig, msg.andx());
     444                 :            : 
     445         [ #  # ]:          0 :                 if ( smb_com_generic_andx )
     446                 :            :                         {
     447                 :          0 :                         val_list* vl = new val_list;
     448                 :          0 :                         vl->append(analyzer->BuildConnVal());
     449                 :          0 :                         vl->append(BuildHeaderVal(hdr));
     450                 :            :                         vl->append(new StringVal(msg.data().length(),
     451                 :          0 :                                         (char *) msg.data().begin()));
     452                 :            : 
     453                 :          0 :                         analyzer->ConnectionEvent(smb_com_generic_andx, vl);
     454                 :          0 :                         }
     455                 :            :                 }
     456                 :          0 :         catch ( const binpac::Exception& )
     457                 :            :                 {
     458                 :          0 :                 Weird("smb_andx_command_failed_to_parse");
     459                 :            :                 }
     460                 :            : 
     461                 :          0 :         return 0;
     462                 :            :         }
     463                 :            : 
     464                 :            : int SMB_Session::ParseTreeConnectAndx(binpac::SMB::SMB_header const& hdr,
     465                 :          0 :                                         SMB_Body const& body)
     466                 :            :         {
     467                 :          0 :         binpac::SMB::SMB_tree_connect_andx req(hdr.unicode());
     468                 :            : 
     469                 :          0 :         req.Parse(body.data(), body.data() + body.length());
     470                 :          0 :         set_andx(1, req.andx());
     471                 :            : 
     472                 :          0 :         BroString* path = ExtractString(req.path());
     473                 :          0 :         BroString* service = ExtractString(req.service());
     474                 :            : 
     475                 :            :         // Replicate path.
     476                 :          0 :         BroString* norm_path = new BroString(path->Bytes(), path->Len(), 1);
     477                 :          0 :         norm_path->ToUpper();
     478                 :            : 
     479                 :          0 :         RecordVal* r = new RecordVal(smb_tree_connect);
     480                 :          0 :         r->Assign(0, new Val(req.flags(), TYPE_COUNT));
     481                 :            :         r->Assign(1, new StringVal(req.password_length(),
     482                 :          0 :                                         (const char*) req.password()));
     483                 :          0 :         r->Assign(3, new StringVal(path));
     484                 :          0 :         r->Assign(4, new StringVal(service));
     485                 :            : 
     486         [ #  # ]:          0 :         if ( strstr_n(norm_path->Len(), norm_path->Bytes(), 5,
     487                 :            :                       (const u_char*) "\\IPC$") != -1 )
     488                 :          0 :                 is_IPC = true;  // TODO: change is_IPC to 0 on tree_disconnect
     489                 :            :         else
     490                 :          0 :                 is_IPC = false;
     491                 :            : 
     492         [ #  # ]:          0 :         delete norm_path;
     493                 :            : 
     494         [ #  # ]:          0 :         if ( smb_com_tree_connect_andx )
     495                 :            :                 {
     496                 :          0 :                 val_list* vl = new val_list;
     497                 :          0 :                 vl->append(analyzer->BuildConnVal());
     498                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     499                 :          0 :                 vl->append(r);
     500                 :            : 
     501                 :          0 :                 analyzer->ConnectionEvent(smb_com_tree_connect_andx, vl);
     502                 :            :                 }
     503                 :            :         else
     504                 :            :                 {
     505         [ #  # ]:          0 :                 delete path;
     506         [ #  # ]:          0 :                 delete service;
     507                 :            :                 }
     508                 :            : 
     509                 :          0 :         return 0;
     510                 :            :         }
     511                 :            : 
     512                 :            : int SMB_Session::ParseTreeDisconnect(int is_orig,
     513                 :            :                                         binpac::SMB::SMB_header const& hdr,
     514                 :          0 :                                         SMB_Body const& body)
     515                 :            :         {
     516                 :          0 :         binpac::SMB::SMB_tree_disconnect msg(hdr.unicode());
     517                 :          0 :         msg.Parse(body.data(), body.data() + body.length());
     518                 :            : 
     519         [ #  # ]:          0 :         if ( smb_com_nt_create_andx )
     520                 :            :                 {
     521                 :          0 :                 val_list* vl = new val_list;
     522                 :          0 :                 vl->append(analyzer->BuildConnVal());
     523                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     524                 :            : 
     525                 :          0 :                 analyzer->ConnectionEvent(smb_com_tree_disconnect, vl);
     526                 :            :                 }
     527                 :            : 
     528                 :          0 :         return 0;
     529                 :            :         }
     530                 :            : 
     531                 :            : int SMB_Session::ParseNtCreateAndx(binpac::SMB::SMB_header const& hdr,
     532                 :          0 :                                         SMB_Body const& body)
     533                 :            :         {
     534                 :          0 :         binpac::SMB::SMB_nt_create_andx req(hdr.unicode());
     535                 :          0 :         req.Parse(body.data(), body.data() + body.length());
     536                 :          0 :         set_andx(1, req.andx());
     537                 :            : 
     538                 :          0 :         BroString* name = ExtractString(req.name());
     539                 :            : 
     540                 :          0 :         IPC_pipe = (enum IPC_named_pipe) lookup_IPC_name(name);
     541                 :            : 
     542         [ #  # ]:          0 :         if ( smb_com_nt_create_andx )
     543                 :            :                 {
     544                 :          0 :                 val_list* vl = new val_list;
     545                 :          0 :                 vl->append(analyzer->BuildConnVal());
     546                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     547                 :          0 :                 vl->append(new StringVal(name));
     548                 :            : 
     549                 :          0 :                 analyzer->ConnectionEvent(smb_com_nt_create_andx, vl);
     550                 :            :                 }
     551                 :            :         else
     552         [ #  # ]:          0 :                 delete name;
     553                 :            : 
     554                 :          0 :         return 0;
     555                 :            :         }
     556                 :            : 
     557                 :            : int SMB_Session::ParseReadAndx(binpac::SMB::SMB_header const& hdr,
     558                 :          0 :                                 SMB_Body const& body)
     559                 :            :         {
     560                 :          0 :         binpac::SMB::SMB_read_andx req;
     561                 :          0 :         req.Parse(body.data(), body.data() + body.length());
     562                 :          0 :         set_andx(1, req.andx());
     563                 :            : 
     564         [ #  # ]:          0 :         if ( smb_com_read_andx )
     565                 :            :                 {
     566                 :          0 :                 val_list* vl = new val_list;
     567                 :          0 :                 vl->append(analyzer->BuildConnVal());
     568                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     569                 :          0 :                 vl->append(new StringVal(""));
     570                 :            : 
     571                 :          0 :                 analyzer->ConnectionEvent(smb_com_read_andx, vl);
     572                 :            :                 }
     573                 :            : 
     574                 :          0 :         return 0;
     575                 :            :         }
     576                 :            : 
     577                 :            : int SMB_Session::ParseReadAndxResponse(binpac::SMB::SMB_header const& hdr,
     578                 :          0 :                                         SMB_Body const& body)
     579                 :            :         {
     580                 :          0 :         binpac::SMB::SMB_read_andx_response resp;
     581                 :          0 :         resp.Parse(body.data(), body.data() + body.length());
     582                 :          0 :         set_andx(0, resp.andx());
     583                 :            : 
     584                 :          0 :         int data_count = resp.data_length();
     585                 :          0 :         const u_char* data = resp.data().begin();
     586                 :            : 
     587         [ #  # ]:          0 :         if ( smb_com_read_andx )
     588                 :            :                 {
     589                 :          0 :                 val_list* vl = new val_list;
     590                 :          0 :                 vl->append(analyzer->BuildConnVal());
     591                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     592                 :          0 :                 vl->append(new StringVal(data_count, (const char*) data));
     593                 :            : 
     594                 :          0 :                 analyzer->ConnectionEvent(smb_com_read_andx, vl);
     595                 :            :                 }
     596                 :            : 
     597                 :          0 :         CheckRPC(0, data_count, data);
     598                 :            : 
     599                 :          0 :         return 0;
     600                 :            :         }
     601                 :            : 
     602                 :            : int SMB_Session::ParseWriteAndx(binpac::SMB::SMB_header const& hdr,
     603                 :          0 :                                 SMB_Body const& body)
     604                 :            :         {
     605                 :          0 :         binpac::SMB::SMB_write_andx req;
     606                 :          0 :         req.Parse(body.data(), body.data() + body.length());
     607                 :          0 :         set_andx(1, req.andx());
     608                 :            : 
     609                 :          0 :         int data_count = req.data_length();
     610                 :          0 :         const u_char* data = req.data().begin();
     611                 :            : 
     612         [ #  # ]:          0 :         if ( smb_com_write_andx )
     613                 :            :                 {
     614                 :          0 :                 val_list* vl = new val_list;
     615                 :          0 :                 vl->append(analyzer->BuildConnVal());
     616                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     617                 :          0 :                 vl->append(new StringVal(data_count, (const char*) data));
     618                 :            : 
     619                 :          0 :                 analyzer->ConnectionEvent(smb_com_write_andx, vl);
     620                 :            :                 }
     621                 :            : 
     622                 :          0 :         CheckRPC(1, data_count, data);
     623                 :            : 
     624                 :          0 :         return 0;
     625                 :            :         }
     626                 :            : 
     627                 :            : int SMB_Session::ParseWriteAndxResponse(binpac::SMB::SMB_header const& hdr,
     628                 :          0 :                                         SMB_Body const& body)
     629                 :            :         {
     630                 :          0 :         binpac::SMB::SMB_write_andx_response resp;
     631                 :          0 :         resp.Parse(body.data(), body.data() + body.length());
     632                 :          0 :         set_andx(0, resp.andx());
     633                 :            : 
     634         [ #  # ]:          0 :         if ( smb_com_write_andx )
     635                 :            :                 {
     636                 :          0 :                 val_list* vl = new val_list;
     637                 :          0 :                 vl->append(analyzer->BuildConnVal());
     638                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     639                 :          0 :                 vl->append(new StringVal(""));
     640                 :            : 
     641                 :          0 :                 analyzer->ConnectionEvent(smb_com_write_andx, vl);
     642                 :            :                 }
     643                 :            : 
     644                 :          0 :         return 0;
     645                 :            :         }
     646                 :            : 
     647                 :            : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
     648                 :            :                                 binpac::SMB::SMB_header const &hdr,
     649                 :            :                                 binpac::SMB::SMB_transaction const &trans,
     650                 :            :                                 int data_count,
     651                 :          0 :                                 binpac::SMB::SMB_transaction_data* data)
     652                 :            :         {
     653         [ #  # ]:          0 :         if ( f )
     654                 :            :                 {
     655                 :          0 :                 val_list* vl = new val_list;
     656                 :            : 
     657                 :          0 :                 vl->append(analyzer->BuildConnVal());
     658                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     659                 :          0 :                 vl->append(BuildTransactionVal(trans));
     660                 :          0 :                 vl->append(BuildTransactionDataVal(data));
     661                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
     662                 :            : 
     663                 :          0 :                 analyzer->ConnectionEvent(f, vl);
     664                 :            :                 }
     665                 :            : 
     666                 :          0 :         else if ( smb_com_transaction )
     667                 :            :                 { // generic transaction
     668                 :            :                 }
     669                 :            : 
     670                 :          0 :         return 0;
     671                 :            :         }
     672                 :            : 
     673                 :            : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
     674                 :            :                         binpac::SMB::SMB_header const &hdr,
     675                 :            :                         binpac::SMB::SMB_transaction_secondary const &trans,
     676                 :          0 :                         int data_count, binpac::SMB::SMB_transaction_data* data)
     677                 :            :         {
     678         [ #  # ]:          0 :         if ( f )
     679                 :            :                 {
     680                 :          0 :                 val_list* vl = new val_list;
     681                 :            : 
     682                 :          0 :                 vl->append(analyzer->BuildConnVal());
     683                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     684                 :          0 :                 vl->append(BuildTransactionVal(trans));
     685                 :          0 :                 vl->append(BuildTransactionDataVal(data));
     686                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
     687                 :            : 
     688                 :          0 :                 analyzer->ConnectionEvent(f, vl);
     689                 :            :                 }
     690                 :            : 
     691                 :          0 :         else if ( smb_com_transaction )
     692                 :            :                 { // generic transaction
     693                 :            :                 }
     694                 :            : 
     695                 :          0 :         return 0;
     696                 :            :         }
     697                 :            : 
     698                 :            : int SMB_Session::TransactionEvent(EventHandlerPtr f, int is_orig,
     699                 :            :                         binpac::SMB::SMB_header const &hdr,
     700                 :            :                         binpac::SMB::SMB_transaction_response const &trans,
     701                 :          0 :                         int data_count, binpac::SMB::SMB_transaction_data* data)
     702                 :            :         {
     703         [ #  # ]:          0 :         if ( f )
     704                 :            :                 {
     705                 :          0 :                 val_list* vl = new val_list;
     706                 :            : 
     707                 :          0 :                 vl->append(analyzer->BuildConnVal());
     708                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     709                 :          0 :                 vl->append(BuildTransactionVal(trans));
     710                 :          0 :                 vl->append(BuildTransactionDataVal(data));
     711                 :          0 :                 vl->append(new Val(is_orig, TYPE_BOOL));
     712                 :            : 
     713                 :          0 :                 analyzer->ConnectionEvent(f, vl);
     714                 :            :                 }
     715                 :            : 
     716                 :          0 :         else if ( smb_com_transaction )
     717                 :            :                 { // generic transaction
     718                 :            :                 }
     719                 :            : 
     720                 :          0 :         return 0;
     721                 :            :         }
     722                 :            : 
     723                 :            : int SMB_Session::ParseTransaction(int is_orig, int cmd,
     724                 :            :                                         binpac::SMB::SMB_header const& hdr,
     725                 :          0 :                                         SMB_Body const& body)
     726                 :            :         {
     727         [ #  # ]:          0 :         switch ( cmd ) {
     728                 :            :         case SMB_COM_TRANSACTION:
     729                 :            :         case SMB_COM_TRANSACTION2:
     730                 :            :         case SMB_COM_TRANSACTION_SECONDARY:
     731                 :            :         case SMB_COM_TRANSACTION2_SECONDARY:
     732                 :            :                 break;
     733                 :            : 
     734                 :            :         default:
     735                 :          0 :                 internal_error("command mismatch for ParseTransaction");
     736                 :            :         }
     737                 :            : 
     738                 :            :         int ret;
     739         [ #  # ]:          0 :         if ( is_orig )
     740                 :            :                 {
     741 [ #  # ][ #  # ]:          0 :                 if ( cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION2 )
     742                 :          0 :                         ret = ParseTransactionRequest(cmd, hdr, body);
     743                 :            : 
     744 [ #  # ][ #  # ]:          0 :                 else if ( cmd == SMB_COM_TRANSACTION_SECONDARY ||
     745                 :            :                           cmd == SMB_COM_TRANSACTION2_SECONDARY )
     746                 :          0 :                         ret = ParseTransactionSecondaryRequest(cmd, hdr, body);
     747                 :            : 
     748                 :            :                 else
     749                 :          0 :                         ret = 0;
     750                 :            :                 }
     751                 :            :         else
     752                 :          0 :                 ret = ParseTransactionResponse(cmd, hdr, body);
     753                 :            : 
     754                 :          0 :         return ret;
     755                 :            :         }
     756                 :            : 
     757                 :            : int SMB_Session::ParseTransactionRequest(int cmd,
     758                 :            :                                         binpac::SMB::SMB_header const& hdr,
     759                 :          0 :                                         SMB_Body const& body)
     760                 :            :         {
     761                 :            :         binpac::SMB::SMB_transaction trans(cmd == SMB_COM_TRANSACTION ? 1 : 2,
     762         [ #  # ]:          0 :                                                 hdr.unicode());
     763                 :            : 
     764                 :          0 :         trans.Parse(body.data(), body.data() + body.length());
     765                 :            : 
     766         [ #  # ]:          0 :         if ( transaction_name )
     767                 :            :                 {
     768                 :          0 :                 Unref(transaction_name);
     769                 :          0 :                 transaction_name = 0;
     770                 :            :                 }
     771                 :            : 
     772         [ #  # ]:          0 :         if ( cmd == SMB_COM_TRANSACTION )
     773                 :            :                 {
     774                 :          0 :                 binpac::SMB::SMB_transaction_data* trans_data = trans.data();
     775                 :            : 
     776                 :            :                 //transaction_name = new StringVal(ExtractString(trans.name()));
     777                 :            :                 //if ( is_orig )
     778                 :            :                 //      Weird(fmt("smb_transaction subcmd: 0x%x", transaction_subcmd));
     779                 :            : 
     780   [ #  #  #  # ]:          0 :                 if ( trans_data->val_case_index() ==
                 [ #  # ]
     781                 :            :                         binpac::SMB::SMB_MAILSLOT_BROWSE &&
     782                 :            :                      trans_data->mailslot() )
     783                 :            :                         { // Mailslot transaction event
     784                 :            :                         return TransactionEvent(smb_com_trans_mailslot, true,
     785                 :          0 :                                 hdr, trans, trans.data_count(), trans.data());
     786                 :            :                         }
     787                 :            : 
     788 [ #  # ][ #  # ]:          0 :                 else if ( trans_data->val_case_index() ==
                 [ #  # ]
     789                 :            :                                 binpac::SMB::SMB_PIPE && trans_data->pipe() )
     790                 :            :                         { // Pipe
     791                 :            :                         return TransactionEvent(smb_com_trans_pipe, true, hdr,
     792                 :          0 :                                 trans, trans.data_count(), trans.data());
     793                 :            :                         }
     794                 :            : 
     795 [ #  # ][ #  # ]:          0 :                 else if ( trans_data->val_case_index() ==
                 [ #  # ]
     796                 :            :                                 binpac::SMB::SMB_RAP && trans_data->rap() )
     797                 :            :                         { // Remote Administration Protocol
     798                 :            :                         return TransactionEvent(smb_com_trans_rap, true, hdr,
     799                 :          0 :                                 trans, trans.data_count(), trans.data());
     800                 :            :                         }
     801                 :            : 
     802                 :            :                 else
     803                 :            :                         {
     804                 :            :                         // SOME UNKNOWN TRANSACTION TYPE - COULD BE RPC STILL!
     805 [ #  # ][ #  # ]:          0 :                         if ( trans.data_count() > 0 && trans.setup_count() == 2 )
                 [ #  # ]
     806                 :            :                                 {
     807         [ #  # ]:          0 :                                 if ( CheckRPC(true, trans.data_count(),
     808                 :            :                                         trans_data->pipe()->data().begin()) )
     809                 :            :                                         {
     810 [ #  # ][ #  # ]:          0 :                                         if ( cmd != SMB_COM_TRANSACTION ||
     811                 :            :                                              transaction_subcmd != 0x26 )
     812                 :          0 :                                                 Weird(fmt("RPC through unknown command: 0x%x/0x%x", cmd, transaction_subcmd));
     813                 :            :                                         }
     814                 :            :                                 }
     815                 :            :                         }
     816                 :            :                 }
     817                 :            : 
     818         [ #  # ]:          0 :         if ( cmd == SMB_COM_TRANSACTION2 )
     819                 :            :                 {
     820      [ #  #  # ]:          0 :                 switch ( transaction_subcmd ) {
     821                 :            :                 case 0x3: // QueryFSInfo
     822                 :            :                 case 0x5: // QueryPathInfo
     823                 :            :                 case 0x7: // QueryFileInfo
     824                 :            :                 case 0x8: // SetFileInfo
     825                 :          0 :                         break;
     826                 :            : 
     827                 :            :                 case 0x10:
     828                 :            :                         // if ( is_orig )
     829                 :            :                         return ParseGetDFSReferral(hdr, trans.param_count(),
     830                 :          0 :                                                 trans.parameters().begin());
     831                 :            : 
     832                 :            :                 default:
     833                 :            :                         // if ( is_orig )
     834                 :            :                         Weird(fmt("Unknown smb_transaction2 subcmd: 0x%x",
     835                 :          0 :                                         transaction_subcmd));
     836                 :            :                         break;
     837                 :            :                 }
     838                 :            :                 }
     839                 :            : 
     840         [ #  # ]:          0 :         if ( smb_com_transaction )
     841                 :            :                 return TransactionEvent(smb_com_transaction, true, hdr,
     842                 :            :                                         trans, trans.data_count(),
     843                 :          0 :                                         trans.data());
     844                 :            :         else
     845                 :          0 :                 return 0;
     846                 :            : 
     847                 :            : #if 0
     848                 :            :         // TODO: LANMAN transaction uses the first u_short of
     849                 :            :         // parameters as subcmd
     850                 :            : 
     851                 :            :         if ( trans.setup_count() > 0 )
     852                 :            :                 transaction_subcmd = (*trans.setup())[0];
     853                 :            : 
     854                 :            :         else if ( strncmp( transaction_name->CheckString(), "\\PIPE\\", 6 ) == 0 )
     855                 :            :                 transaction_subcmd = 0;
     856                 :            : 
     857                 :            :         else if ( strncmp( transaction_name->CheckString(), "\\MAILSLOT\\", 10 ) == 0 )
     858                 :            :                 transaction_subcmd = 0;
     859                 :            : 
     860                 :            :         else
     861                 :            :                 Weird("transaction_subcmd_missing");
     862                 :            : #endif
     863                 :            :         }
     864                 :            : 
     865                 :            : int SMB_Session::ParseTransactionSecondaryRequest(int cmd,
     866                 :            :                                         binpac::SMB::SMB_header const& hdr,
     867                 :          0 :                                         SMB_Body const& body)
     868                 :            :         {
     869                 :          0 :         binpac::SMB::SMB_transaction_secondary trans(hdr.unicode());
     870                 :          0 :         trans.Parse(body.data(), body.data() + body.length());
     871                 :            : 
     872                 :            :         return TransactionEvent(smb_com_transaction2, true, hdr,
     873                 :          0 :                                 trans, trans.data_count(), trans.data());
     874                 :            :         }
     875                 :            : 
     876                 :            : int SMB_Session::ParseTransactionResponse(int cmd,
     877                 :            :                                         binpac::SMB::SMB_header const& hdr,
     878                 :          0 :                                         SMB_Body const& body)
     879                 :            :         {
     880                 :          0 :         binpac::SMB::SMB_transaction_response trans(hdr.unicode());
     881                 :          0 :         trans.Parse(body.data(), body.data() + body.length());
     882                 :            : 
     883         [ #  # ]:          0 :         if ( body.word_count() == 0 )
     884                 :            :                 { // interim response
     885                 :            :                 // Does the transaction get parsed correctly?!
     886                 :            :                 return TransactionEvent(smb_com_transaction, false, hdr,
     887                 :          0 :                                         trans, 0, NULL);
     888                 :            :                 }
     889                 :            : 
     890                 :            :         return TransactionEvent(smb_com_transaction, false, hdr,
     891                 :          0 :                                 trans, trans.data_count(), trans.data());
     892                 :            :         }
     893                 :            : 
     894                 :            : int SMB_Session::ParseGetDFSReferral(binpac::SMB::SMB_header const& hdr,
     895                 :          0 :                                         int param_count, const u_char* param)
     896                 :            :         {
     897                 :          0 :         binpac::SMB::SMB_get_dfs_referral req(hdr.unicode());
     898                 :          0 :         req.Parse(param, param + param_count);
     899                 :            : 
     900         [ #  # ]:          0 :         if ( smb_get_dfs_referral )
     901                 :            :                 {
     902                 :          0 :                 val_list* vl = new val_list;
     903                 :          0 :                 vl->append(analyzer->BuildConnVal());
     904                 :          0 :                 vl->append(BuildHeaderVal(hdr));
     905                 :          0 :                 vl->append(new Val(req.max_referral_level(), TYPE_COUNT));
     906                 :          0 :                 vl->append(new StringVal(ExtractString(req.file_name())));
     907                 :            : 
     908                 :          0 :                 analyzer->ConnectionEvent(smb_get_dfs_referral, vl);
     909                 :            :                 }
     910                 :            : 
     911                 :          0 :         return 0;
     912                 :            :         }
     913                 :            : 
     914                 :          0 : int SMB_Session::AndxOffset(int is_orig, int& next_command) const
     915                 :            :         {
     916         [ #  # ]:          0 :         if ( ! andx(is_orig) )
     917                 :          0 :                 return -1;
     918                 :            : 
     919                 :          0 :         next_command = andx(is_orig)->command();
     920         [ #  # ]:          0 :         if ( next_command != 0xff )
     921                 :          0 :                 return andx(is_orig)->offset();
     922                 :            :         else
     923                 :          0 :                 return -1;
     924                 :            :         }
     925                 :            : 
     926                 :          0 : void SMB_Session::Weird(const char* msg)
     927                 :            :         {
     928                 :          0 :         analyzer->Weird(msg);
     929                 :          0 :         }
     930                 :            : 
     931                 :            : // Extract a NUL-terminated string from [data, data+len-1]. The
     932                 :            : // input can be in Unicode (little endian), and the returned string
     933                 :            : // will be in ASCII.  Note, Unicode strings have NUL characters
     934                 :            : // at the end of them already.  Adding an additional NUL byte at
     935                 :            : // the end leads to embedded-NUL warnings (CheckString() run_time error).
     936                 :            : 
     937                 :          0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_string const* s)
     938                 :            :         {
     939         [ #  # ]:          0 :         return s->unicode() ? ExtractString(s->u()) : ExtractString(s->a());
     940                 :            :         }
     941                 :            : 
     942                 :          0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_ascii_string const* s)
     943                 :            :         {
     944                 :          0 :         bool add_NUL = true;
     945                 :          0 :         int n = s->size();
     946                 :            : 
     947   [ #  #  #  # ]:          0 :         if ( n > 0 && (*s)[n - 1] == '\0' )
                 [ #  # ]
     948                 :          0 :                 add_NUL = false;        // already has a NUL
     949                 :            : 
     950         [ #  # ]:          0 :         if ( add_NUL )
     951                 :          0 :                 ++n;
     952                 :            : 
     953                 :          0 :         u_char* b = new u_char[n];
     954                 :            :         int i;
     955         [ #  # ]:          0 :         for ( i = 0; i < int(s->size()); ++i )
     956                 :          0 :                 b[i] = (*s)[i];
     957                 :            : 
     958         [ #  # ]:          0 :         if ( add_NUL )
     959                 :          0 :                 b[i] = '\0';
     960                 :            : 
     961                 :          0 :         return new BroString(1, b, n - 1);
     962                 :            :         }
     963                 :            : 
     964                 :          0 : BroString* SMB_Session::ExtractString(binpac::SMB::SMB_unicode_string const* s)
     965                 :            :         {
     966                 :          0 :         bool add_NUL = true;
     967                 :          0 :         int n = s->s()->size();
     968                 :            : 
     969   [ #  #  #  # ]:          0 :         if ( n > 0 && ((*s->s())[n - 1] & 0xff) == '\0' )
                 [ #  # ]
     970                 :          0 :                 add_NUL = false;        // already has a NUL
     971                 :            : 
     972         [ #  # ]:          0 :         if ( add_NUL )
     973                 :          0 :                 ++n;
     974                 :            : 
     975                 :          0 :         u_char* b = new u_char[n];
     976                 :            : 
     977                 :            :         int i;
     978         [ #  # ]:          0 :         for ( i = 0; i < int(s->s()->size()); ++i )
     979                 :            :                 {
     980                 :          0 :                 uint16 x = (*s->s())[i];
     981         [ #  # ]:          0 :                 if ( x & 0xff00 )
     982                 :          0 :                         Weird(fmt("unicode string confusion: 0x%04x", x));
     983                 :            : 
     984                 :          0 :                 b[i] = u_char(x & 0xff);
     985                 :            :                 }
     986                 :            : 
     987         [ #  # ]:          0 :         if ( add_NUL )
     988                 :          0 :                 b[i] = '\0';
     989                 :            : 
     990                 :          0 :         return new BroString(1, b, n - 1);
     991                 :            :         }
     992                 :            : 
     993                 :          0 : Val* SMB_Session::BuildHeaderVal(binpac::SMB::SMB_header const& hdr)
     994                 :            :         {
     995                 :          0 :         RecordVal* r = new RecordVal(smb_hdr);
     996                 :            : 
     997                 :          0 :         unsigned int status = 0;
     998                 :            : 
     999                 :            :         try
    1000                 :            :                 {
    1001                 :            :                 // FIXME: does this work?  We need to catch exceptions :-(
    1002                 :            :                 // or use guard functions.
    1003                 :            :                 status = hdr.status()->status() ||
    1004                 :            :                             hdr.status()->dos_error()->error_class() << 24 ||
    1005   [ #  #  #  # ]:          0 :                             hdr.status()->dos_error()->error();
                 [ #  # ]
    1006                 :            :                 }
    1007                 :          0 :         catch ( const binpac::Exception& )
    1008                 :            :                 { // do nothing
    1009                 :            :                 }
    1010                 :            : 
    1011                 :          0 :         r->Assign(0, new Val(hdr.command(), TYPE_COUNT));
    1012                 :          0 :         r->Assign(1, new Val(status, TYPE_COUNT));
    1013                 :          0 :         r->Assign(2, new Val(hdr.flags(), TYPE_COUNT));
    1014                 :          0 :         r->Assign(3, new Val(hdr.flags2(), TYPE_COUNT));
    1015                 :          0 :         r->Assign(4, new Val(hdr.tid(), TYPE_COUNT));
    1016                 :          0 :         r->Assign(5, new Val(hdr.pid(), TYPE_COUNT));
    1017                 :          0 :         r->Assign(6, new Val(hdr.uid(), TYPE_COUNT));
    1018                 :          0 :         r->Assign(7, new Val(hdr.mid(), TYPE_COUNT));
    1019                 :            : 
    1020                 :          0 :         return r;
    1021                 :            :         }
    1022                 :            : 
    1023                 :          0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction const& trans)
    1024                 :            :         {
    1025                 :          0 :         RecordVal* r = new RecordVal(smb_trans);
    1026                 :            : 
    1027                 :            :         // r->Assign(0, new Val(variable, type));
    1028                 :            : 
    1029                 :          0 :         return r;
    1030                 :            :         }
    1031                 :            : 
    1032                 :          0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction_secondary const& trans)
    1033                 :            :         {
    1034                 :          0 :         RecordVal* r = new RecordVal(smb_trans);
    1035                 :            : 
    1036                 :            :         // r->Assign(0, new Val(variable, type));
    1037                 :            : 
    1038                 :          0 :         return r;
    1039                 :            :         }
    1040                 :            : 
    1041                 :          0 : Val* SMB_Session::BuildTransactionVal(binpac::SMB::SMB_transaction_response const& trans)
    1042                 :            :         {
    1043                 :          0 :         RecordVal* r = new RecordVal(smb_trans);
    1044                 :            : 
    1045                 :            :         // r->Assign(0, new Val(variable, type));
    1046                 :            : 
    1047                 :          0 :         return r;
    1048                 :            :         }
    1049                 :            : 
    1050                 :          0 : Val* SMB_Session::BuildTransactionDataVal(binpac::SMB::SMB_transaction_data *data)
    1051                 :            :         {
    1052                 :          0 :         RecordVal* r = new RecordVal(smb_trans_data);
    1053                 :            : 
    1054                 :            :         // r->Assign(0, new Val(variable, type));
    1055                 :            : 
    1056                 :          0 :         return r;
    1057                 :            :         }
    1058                 :            : 
    1059                 :          0 : bool SMB_Session::LooksLikeRPC(int len, const u_char* msg)
    1060                 :            :         {
    1061                 :            :         try
    1062                 :            :                 {
    1063                 :          0 :                 binpac::DCE_RPC_Simple::DCE_RPC_Header h;
    1064                 :          0 :                 h.Parse(msg, msg + len);
    1065                 :            : 
    1066   [ #  #  #  # ]:          0 :                 if ( h.rpc_vers() == 5 && h.rpc_vers_minor() == 0 )
                 [ #  # ]
    1067                 :            :                         {
    1068                 :          0 :                         unsigned short frag_len = h.frag_length();
    1069   [ #  #  #  # ]:          0 :                         if ( frag_len == len ||
    1070                 :            :                              BYTEORDER_SWAP16(frag_len) == len )
    1071                 :            :                                 {
    1072         [ #  # ]:          0 :                                 if ( ! is_IPC && DEBUG_smb_ipc )
    1073                 :          0 :                                         analyzer->Weird("TreeConnect to IPC missing");
    1074                 :          0 :                                 return true;
    1075                 :            :                                 }
    1076                 :            :                         else
    1077                 :            :                                 {
    1078                 :          0 :                                 analyzer->Weird(fmt("endianness %d", h.byteorder()));
    1079                 :            :                                 analyzer->Weird(fmt("length mismatch: %d != %d",
    1080                 :          0 :                                         h.frag_length(), len));
    1081                 :          0 :                                 return false;
    1082                 :            :                                 }
    1083         [ #  # ]:          0 :                         }
    1084                 :            :                 }
    1085                 :          0 :         catch ( const binpac::Exception& )
    1086                 :            :                 { // do nothing
    1087                 :            :                 }
    1088                 :            : 
    1089                 :          0 :         return false;
    1090                 :            :         }
    1091                 :            : 
    1092                 :          0 : bool SMB_Session::CheckRPC(int is_orig, int data_count, const u_char *data)
    1093                 :            :         {
    1094         [ #  # ]:          0 :         if ( LooksLikeRPC(data_count, data) )
    1095                 :            :                 {
    1096         [ #  # ]:          0 :                 if ( ! dce_rpc_session )
    1097                 :          0 :                         dce_rpc_session = new DCE_RPC_Session(analyzer);
    1098                 :            : 
    1099                 :          0 :                 dce_rpc_session->DeliverPDU(is_orig, data_count, data);
    1100                 :            : 
    1101                 :          0 :                 return true;
    1102                 :            :                 }
    1103                 :            : 
    1104                 :          0 :         return false;
    1105                 :            :         }
    1106                 :            : 
    1107                 :          0 : Contents_SMB::Contents_SMB(Connection* conn, bool orig, SMB_Session* s)
    1108                 :          0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_SMB, conn, orig)
    1109                 :            :         {
    1110                 :          0 :         smb_session = s;
    1111                 :          0 :         msg_buf = 0;
    1112                 :          0 :         msg_len = 0;
    1113                 :          0 :         buf_len = 0;
    1114                 :          0 :         buf_n = 0;
    1115                 :          0 :         }
    1116                 :            : 
    1117                 :          0 : void Contents_SMB::InitMsgBuf()
    1118                 :            :         {
    1119         [ #  # ]:          0 :         delete [] msg_buf;
    1120                 :          0 :         msg_buf = new u_char[msg_len];
    1121                 :          0 :         buf_len = msg_len;
    1122                 :          0 :         buf_n = 0;
    1123                 :          0 :         }
    1124                 :            : 
    1125                 :          0 : Contents_SMB::~Contents_SMB()
    1126                 :            :         {
    1127 [ #  # ][ #  # ]:          0 :         delete [] msg_buf;
                 [ #  # ]
    1128 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
    1129                 :            : 
    1130                 :          0 : void Contents_SMB::DeliverSMB(int len, const u_char* data)
    1131                 :            :         {
    1132                 :            :         // Check the 4-byte header.
    1133         [ #  # ]:          0 :         if ( strncmp((const char*) data, "\xffSMB", 4) )
    1134                 :            :                 {
    1135                 :            :                 Conn()->Weird(fmt("SMB-over-TCP header error: %02x%02x%02x%02x, \\x%02x%c%c%c",
    1136                 :            :                         dshdr[0], dshdr[1], dshdr[2], dshdr[3],
    1137                 :          0 :                         data[0], data[1], data[2], data[3]));
    1138                 :          0 :                 SetSkip(1);
    1139                 :            :                 }
    1140                 :            :         else
    1141                 :          0 :                 smb_session->Deliver(IsOrig(), len, data);
    1142                 :            : 
    1143                 :          0 :         buf_n = 0;
    1144                 :          0 :         msg_len = 0;
    1145                 :          0 :         }
    1146                 :            : 
    1147                 :          0 : void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig)
    1148                 :            :         {
    1149                 :          0 :         TCP_SupportAnalyzer::DeliverStream(len, data, orig);
    1150                 :            : 
    1151         [ #  # ]:          0 :         while ( len > 0 )
    1152                 :            :                 {
    1153         [ #  # ]:          0 :                 if ( ! msg_len )
    1154                 :            :                         {
    1155                 :            :                         // Get the SMB-over-TCP header (4 bytes).
    1156 [ #  # ][ #  # ]:          0 :                         while ( buf_n < 4 && len > 0 )
    1157                 :            :                                 {
    1158                 :          0 :                                 dshdr[buf_n] = *data;
    1159                 :          0 :                                 ++buf_n; ++data; --len;
    1160                 :            :                                 }
    1161                 :            : 
    1162         [ #  # ]:          0 :                         if ( buf_n < 4 )
    1163                 :          0 :                                 return;
    1164                 :            : 
    1165                 :          0 :                         buf_n = 0;
    1166         [ #  # ]:          0 :                         for ( int i = 1; i < 4; ++i )
    1167                 :          0 :                                 msg_len = ( msg_len << 8 ) + dshdr[i];
    1168                 :            : 
    1169         [ #  # ]:          0 :                         if ( dshdr[0] != 0 )
    1170                 :            :                                 {
    1171                 :            :                                 // Netbios header indicates this is NOT
    1172                 :            :                                 // a session message ...
    1173                 :            :                                 //      0x81 = session request
    1174                 :            :                                 //      0x82 = positive response
    1175                 :            :                                 //      0x83 = neg response
    1176                 :            :                                 //      0x84 = retarget(?)
    1177                 :            :                                 //      0x85 = keepalive
    1178                 :            :                                 // Maybe we should just generate a Netbios
    1179                 :            :                                 // event and die?
    1180                 :          0 :                                 Conn()->Weird("SMB checked Netbios type and found != 0");
    1181                 :          0 :                                 SetSkip(1);
    1182                 :          0 :                                 return;
    1183                 :            :                                 }
    1184                 :            : 
    1185         [ #  # ]:          0 :                         else if ( msg_len <= 4 )
    1186                 :            :                                 {
    1187                 :          0 :                                 Conn()->Weird("SMB message length error");
    1188                 :          0 :                                 SetSkip(1);
    1189                 :          0 :                                 return;
    1190                 :            :                                 }
    1191                 :            :                         }
    1192                 :            : 
    1193 [ #  # ][ #  # ]:          0 :                 if ( buf_n == 0 && msg_len <= len )
    1194                 :            :                         {
    1195                 :            :                         // The fast lane:
    1196                 :            :                         // Keep msg_len -- it will be changed in DeliverSMB
    1197                 :          0 :                         int mlen = msg_len;
    1198                 :          0 :                         DeliverSMB(msg_len, data);
    1199                 :          0 :                         len -= mlen;
    1200                 :          0 :                         data += mlen;
    1201                 :            :                         }
    1202                 :            : 
    1203                 :            :                 else
    1204                 :            :                         {
    1205         [ #  # ]:          0 :                         if ( buf_len < msg_len )
    1206                 :          0 :                                 InitMsgBuf();
    1207                 :            : 
    1208 [ #  # ][ #  # ]:          0 :                         while ( buf_n < msg_len && len > 0 )
    1209                 :            :                                 {
    1210                 :          0 :                                 msg_buf[buf_n] = *data;
    1211                 :          0 :                                 ++buf_n;
    1212                 :          0 :                                 ++data;
    1213                 :          0 :                                 --len;
    1214                 :            :                                 }
    1215                 :            : 
    1216         [ #  # ]:          0 :                         if ( buf_n < msg_len )
    1217                 :          0 :                                 return;
    1218                 :            : 
    1219                 :          0 :                         DeliverSMB(msg_len, msg_buf);
    1220                 :            :                         }
    1221                 :            :                 }
    1222                 :            :         }
    1223                 :            : 
    1224                 :          0 : SMB_Analyzer::SMB_Analyzer(Connection* conn)
    1225                 :          0 : : TCP_ApplicationAnalyzer(AnalyzerTag::SMB, conn)
    1226                 :            :         {
    1227                 :          0 :         smb_session = new SMB_Session(this);
    1228                 :          0 :         o_smb = new Contents_SMB(conn, true, smb_session);
    1229                 :          0 :         r_smb = new Contents_SMB(conn, false, smb_session);
    1230                 :          0 :         AddSupportAnalyzer(o_smb);
    1231                 :          0 :         AddSupportAnalyzer(r_smb);
    1232                 :          0 :         }
    1233                 :            : 
    1234                 :          0 : SMB_Analyzer::~SMB_Analyzer()
    1235                 :            :         {
    1236 [ #  # ][ #  # ]:          0 :         delete smb_session;
                 [ #  # ]
    1237 [ +  - ][ +  - ]:          6 :         }
         [ #  # ][ #  # ]
                 [ #  # ]

Generated by: LCOV version 1.8