LCOV - code coverage report
Current view: top level - src - NVT.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 324 0.6 %
Date: 2010-12-13 Functions: 2 34 5.9 %
Branches: 2 249 0.8 %

           Branch data     Line data    Source code
       1                 :            : // $Id: NVT.cc 6916 2009-09-24 20:48:36Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <stdlib.h>
       8                 :            : 
       9                 :            : #include "NVT.h"
      10                 :            : #include "NetVar.h"
      11                 :            : #include "Event.h"
      12                 :            : #include "TCP.h"
      13                 :            : 
      14                 :            : #define IS_3_BYTE_OPTION(c) (c >= 251 && c <= 254)
      15                 :            : 
      16                 :            : #define TELNET_OPT_SB 250
      17                 :            : #define TELNET_OPT_SE 240
      18                 :            : 
      19                 :            : #define TELNET_OPT_IS 0
      20                 :            : #define TELNET_OPT_SEND 1
      21                 :            : 
      22                 :            : #define TELNET_OPT_WILL 251
      23                 :            : #define TELNET_OPT_WONT 252
      24                 :            : #define TELNET_OPT_DO 253
      25                 :            : #define TELNET_OPT_DONT 254
      26                 :            : 
      27                 :            : #define TELNET_IAC 255
      28                 :            : 
      29                 :          0 : TelnetOption::TelnetOption(NVT_Analyzer* arg_endp, unsigned int arg_code)
      30                 :            :         {
      31                 :          0 :         endp = arg_endp;
      32                 :          0 :         code = arg_code;
      33                 :          0 :         flags = 0;
      34                 :          0 :         active = 0;
      35                 :          0 :         }
      36                 :            : 
      37                 :          0 : void TelnetOption::RecvOption(unsigned int type)
      38                 :            :         {
      39                 :          0 :         TelnetOption* peer = endp->FindPeerOption(code);
      40         [ #  # ]:          0 :         if ( ! peer )
      41                 :          0 :                 internal_error("option peer missing in TelnetOption::RecvOption");
      42                 :            : 
      43                 :            :         // WILL/WONT/DO/DONT are messages we've *received* from our peer.
      44   [ #  #  #  #  :          0 :         switch ( type ) {
                      # ]
      45                 :            :         case TELNET_OPT_WILL:
      46 [ #  # ][ #  # ]:          0 :                 if ( SaidDont() || peer->SaidWont() || peer->IsActive() )
         [ #  # ][ #  # ]
      47                 :          0 :                         InconsistentOption(type);
      48                 :            : 
      49                 :          0 :                 peer->SetWill();
      50                 :            : 
      51         [ #  # ]:          0 :                 if ( SaidDo() )
      52                 :          0 :                         peer->SetActive(1);
      53                 :          0 :                 break;
      54                 :            : 
      55                 :            :         case TELNET_OPT_WONT:
      56 [ #  # ][ #  # ]:          0 :                 if ( peer->SaidWill() && ! SaidDont() )
                 [ #  # ]
      57                 :          0 :                         InconsistentOption(type);
      58                 :            : 
      59                 :          0 :                 peer->SetWont();
      60                 :            : 
      61         [ #  # ]:          0 :                 if ( SaidDont() )
      62                 :          0 :                         peer->SetActive(0);
      63                 :          0 :                 break;
      64                 :            : 
      65                 :            :         case TELNET_OPT_DO:
      66 [ #  # ][ #  # ]:          0 :                 if ( SaidWont() || peer->SaidDont() || IsActive() )
         [ #  # ][ #  # ]
      67                 :          0 :                         InconsistentOption(type);
      68                 :            : 
      69                 :          0 :                 peer->SetDo();
      70                 :            : 
      71         [ #  # ]:          0 :                 if ( SaidWill() )
      72                 :          0 :                         SetActive(1);
      73                 :          0 :                 break;
      74                 :            : 
      75                 :            :         case TELNET_OPT_DONT:
      76 [ #  # ][ #  # ]:          0 :                 if ( peer->SaidDo() && ! SaidWont() )
                 [ #  # ]
      77                 :          0 :                         InconsistentOption(type);
      78                 :            : 
      79                 :          0 :                 peer->SetDont();
      80                 :            : 
      81         [ #  # ]:          0 :                 if ( SaidWont() )
      82                 :          0 :                         SetActive(0);
      83                 :          0 :                 break;
      84                 :            : 
      85                 :            :         default:
      86                 :          0 :                 internal_error("bad option type in TelnetOption::RecvOption");
      87                 :            :         }
      88                 :          0 :         }
      89                 :            : 
      90                 :          0 : void TelnetOption::RecvSubOption(u_char* /* data */, int /* len */)
      91                 :            :         {
      92                 :          0 :         }
      93                 :            : 
      94                 :          0 : void TelnetOption::SetActive(int is_active)
      95                 :            :         {
      96                 :          0 :         active = is_active;
      97                 :          0 :         }
      98                 :            : 
      99                 :          0 : void TelnetOption::InconsistentOption(unsigned int /* type */)
     100                 :            :         {
     101                 :          0 :         endp->Event(inconsistent_option);
     102                 :          0 :         }
     103                 :            : 
     104                 :          0 : void TelnetOption::BadOption()
     105                 :            :         {
     106                 :          0 :         endp->Event(bad_option);
     107                 :          0 :         }
     108                 :            : 
     109                 :            : 
     110                 :          0 : void TelnetTerminalOption::RecvSubOption(u_char* data, int len)
     111                 :            :         {
     112         [ #  # ]:          0 :         if ( len <= 0 )
     113                 :            :                 {
     114                 :          0 :                 BadOption();
     115                 :          0 :                 return;
     116                 :            :                 }
     117                 :            : 
     118         [ #  # ]:          0 :         if ( data[0] == TELNET_OPT_SEND )
     119                 :          0 :                 return;
     120                 :            : 
     121         [ #  # ]:          0 :         if ( data[0] != TELNET_OPT_IS )
     122                 :            :                 {
     123                 :          0 :                 BadOption();
     124                 :          0 :                 return;
     125                 :            :                 }
     126                 :            : 
     127                 :          0 :         endp->SetTerminal(data + 1, len - 1);
     128                 :            :         }
     129                 :            : 
     130                 :            : 
     131                 :            : #define ENCRYPT_SET_ALGORITHM 0
     132                 :            : #define ENCRYPT_SUPPORT_ALGORITM 1
     133                 :            : #define ENCRYPT_REPLY 2
     134                 :            : #define ENCRYPT_STARTING_TO_ENCRYPT 3
     135                 :            : #define ENCRYPT_NO_LONGER_ENCRYPTING 4
     136                 :            : #define ENCRYPT_REQUEST_START_TO_ENCRYPT 5
     137                 :            : #define ENCRYPT_REQUEST_NO_LONGER_ENCRYPT 6
     138                 :            : #define ENCRYPT_ENCRYPT_KEY 7
     139                 :            : #define ENCRYPT_DECRYPT_KEY 8
     140                 :            : 
     141                 :          0 : void TelnetEncryptOption::RecvSubOption(u_char* data, int len)
     142                 :            :         {
     143         [ #  # ]:          0 :         if ( ! active )
     144                 :            :                 {
     145                 :          0 :                 InconsistentOption(0);
     146                 :          0 :                 return;
     147                 :            :                 }
     148                 :            : 
     149         [ #  # ]:          0 :         if ( len <= 0 )
     150                 :            :                 {
     151                 :          0 :                 BadOption();
     152                 :          0 :                 return;
     153                 :            :                 }
     154                 :            : 
     155                 :          0 :         unsigned int opt = data[0];
     156                 :            : 
     157         [ #  # ]:          0 :         if ( opt == ENCRYPT_REQUEST_START_TO_ENCRYPT )
     158                 :          0 :                 ++did_encrypt_request;
     159                 :            : 
     160         [ #  # ]:          0 :         else if ( opt == ENCRYPT_STARTING_TO_ENCRYPT )
     161                 :            :                 {
     162                 :            :                 TelnetEncryptOption* peer =
     163                 :          0 :                         (TelnetEncryptOption*) endp->FindPeerOption(code);
     164                 :            : 
     165         [ #  # ]:          0 :                 if ( ! peer )
     166                 :          0 :                         internal_error("option peer missing in TelnetEncryptOption::RecvSubOption");
     167                 :            : 
     168 [ #  # ][ #  # ]:          0 :                 if ( peer->DidRequest() || peer->DoingEncryption() ||
         [ #  # ][ #  # ]
     169                 :            :                      peer->Endpoint()->AuthenticationHasBeenAccepted() )
     170                 :            :                         {
     171                 :          0 :                         endp->SetEncrypting(1);
     172                 :          0 :                         ++doing_encryption;
     173                 :            :                         }
     174                 :            :                 else
     175                 :          0 :                         InconsistentOption(0);
     176                 :            :                 }
     177                 :            :         }
     178                 :            : 
     179                 :            : #define HERE_IS_AUTHENTICATION 0
     180                 :            : #define SEND_ME_AUTHENTICATION 1
     181                 :            : #define AUTHENTICATION_STATUS 2
     182                 :            : #define AUTHENTICATION_NAME 3
     183                 :            : 
     184                 :            : #define AUTH_REJECT 1
     185                 :            : #define AUTH_ACCEPT 2
     186                 :            : 
     187                 :          0 : void TelnetAuthenticateOption::RecvSubOption(u_char* data, int len)
     188                 :            :         {
     189         [ #  # ]:          0 :         if ( len <= 0 )
     190                 :            :                 {
     191                 :          0 :                 BadOption();
     192                 :          0 :                 return;
     193                 :            :                 }
     194                 :            : 
     195   [ #  #  #  #  :          0 :         switch ( data[0] ) {
                      # ]
     196                 :            :         case HERE_IS_AUTHENTICATION:
     197                 :            :                 {
     198                 :            :                 TelnetAuthenticateOption* peer =
     199                 :          0 :                         (TelnetAuthenticateOption*) endp->FindPeerOption(code);
     200                 :            : 
     201         [ #  # ]:          0 :                 if ( ! peer )
     202                 :          0 :                         internal_error("option peer missing in TelnetAuthenticateOption::RecvSubOption");
     203                 :            : 
     204         [ #  # ]:          0 :                 if ( ! peer->DidRequestAuthentication() )
     205                 :          0 :                         InconsistentOption(0);
     206                 :            :                 }
     207                 :          0 :                 break;
     208                 :            : 
     209                 :            :         case SEND_ME_AUTHENTICATION:
     210                 :          0 :                 ++authentication_requested;
     211                 :          0 :                 break;
     212                 :            : 
     213                 :            :         case AUTHENTICATION_STATUS:
     214         [ #  # ]:          0 :                 if ( len <= 1 )
     215                 :            :                         {
     216                 :          0 :                         BadOption();
     217                 :          0 :                         return;
     218                 :            :                         }
     219                 :            : 
     220         [ #  # ]:          0 :                 if ( data[1] == AUTH_REJECT )
     221                 :          0 :                         endp->AuthenticationRejected();
     222         [ #  # ]:          0 :                 else if ( data[1] == AUTH_ACCEPT )
     223                 :          0 :                         endp->AuthenticationAccepted();
     224                 :            :                 else
     225                 :            :                         {
     226                 :            :                         // Don't complain, there may be replies we don't
     227                 :            :                         // know about.
     228                 :            :                         }
     229                 :          0 :                 break;
     230                 :            : 
     231                 :            :         case AUTHENTICATION_NAME:
     232                 :            :                 {
     233                 :          0 :                 char* auth_name = new char[len];
     234                 :          0 :                 safe_strncpy(auth_name, (char*) data + 1, len);
     235                 :          0 :                 endp->SetAuthName(auth_name);
     236                 :            :                 }
     237                 :          0 :                 break;
     238                 :            : 
     239                 :            :         default:
     240                 :          0 :                 BadOption();
     241                 :            :         }
     242                 :            :         }
     243                 :            : 
     244                 :            : #define ENVIRON_IS 0
     245                 :            : #define ENVIRON_SEND 1
     246                 :            : #define ENVIRON_INFO 2
     247                 :            : 
     248                 :            : #define ENVIRON_VAR 0
     249                 :            : #define ENVIRON_VAL 1
     250                 :            : #define ENVIRON_ESC 2
     251                 :            : #define ENVIRON_USERVAR 3
     252                 :            : 
     253                 :          0 : void TelnetEnvironmentOption::RecvSubOption(u_char* data, int len)
     254                 :            :         {
     255         [ #  # ]:          0 :         if ( len <= 0 )
     256                 :            :                 {
     257                 :          0 :                 BadOption();
     258                 :          0 :                 return;
     259                 :            :                 }
     260                 :            : 
     261         [ #  # ]:          0 :         if ( data[0] == ENVIRON_SEND )
     262                 :            :                 //### We should track the dialog and make sure both sides agree.
     263                 :          0 :                 return;
     264                 :            : 
     265 [ #  # ][ #  # ]:          0 :         if ( data[0] != ENVIRON_IS && data[0] != ENVIRON_INFO )
     266                 :            :                 {
     267                 :          0 :                 BadOption();
     268                 :          0 :                 return;
     269                 :            :                 }
     270                 :            : 
     271                 :          0 :         --len;  // Discard code.
     272                 :          0 :         ++data;
     273                 :            : 
     274         [ #  # ]:          0 :         while ( len > 0 )
     275                 :            :                 {
     276                 :            :                 int code1, code2;
     277                 :          0 :                 char* var_name = ExtractEnv(data, len, code1);
     278                 :          0 :                 char* var_val = ExtractEnv(data, len, code2);
     279                 :            : 
     280   [ #  #  #  # ]:          0 :                 if ( ! var_name || ! var_val ||
         [ #  # ][ #  # ]
                 [ #  # ]
     281                 :            :                      (code1 != ENVIRON_VAR && code1 != ENVIRON_USERVAR) ||
     282                 :            :                      code2 != ENVIRON_VAL )
     283                 :            :                         {
     284                 :            :                         // One of var_name/var_val might be set; avoid leak.
     285         [ #  # ]:          0 :                         delete [] var_name;
     286         [ #  # ]:          0 :                         delete [] var_val;
     287                 :            : 
     288                 :          0 :                         BadOption();
     289                 :          0 :                         break;
     290                 :            :                         }
     291                 :            : 
     292                 :            :                 static_cast<TCP_ApplicationAnalyzer*>
     293                 :            :                         (endp->Parent())->SetEnv(endp->IsOrig(),
     294                 :          0 :                                                         var_name, var_val);
     295                 :            :                 }
     296                 :            :         }
     297                 :            : 
     298                 :          0 : char* TelnetEnvironmentOption::ExtractEnv(u_char*& data, int& len, int& code)
     299                 :            :         {
     300                 :          0 :         code = data[0];
     301                 :            : 
     302 [ #  # ][ #  # ]:          0 :         if ( code != ENVIRON_VAR && code != ENVIRON_VAL &&
                 [ #  # ]
     303                 :            :              code != ENVIRON_USERVAR )
     304                 :          0 :                 return 0;
     305                 :            : 
     306                 :            :         // Move past code.
     307                 :          0 :         --len;
     308                 :          0 :         ++data;
     309                 :            : 
     310                 :            :         // Find the end of this piece of the option.
     311                 :          0 :         u_char* data_end = data + len;
     312                 :            :         u_char* d;
     313         [ #  # ]:          0 :         for ( d = data; d < data_end; ++d )
     314                 :            :                 {
     315 [ #  # ][ #  # ]:          0 :                 if ( *d == ENVIRON_VAR || *d == ENVIRON_VAL || *d == ENVIRON_USERVAR )
                 [ #  # ]
     316                 :          0 :                         break;
     317                 :            : 
     318         [ #  # ]:          0 :                 if ( *d == ENVIRON_ESC )
     319                 :            :                         {
     320                 :          0 :                         ++d;    // move past ESC
     321         [ #  # ]:          0 :                         if ( d >= data_end )
     322                 :          0 :                                 return 0;
     323                 :          0 :                         break;
     324                 :            :                         }
     325                 :            :                 }
     326                 :            : 
     327                 :          0 :         int size = d - data;
     328                 :          0 :         char* env = new char[size+1];
     329                 :            : 
     330                 :            :         // Now copy into env.
     331                 :          0 :         int d_ind = 0;
     332                 :            :         int i;
     333         [ #  # ]:          0 :         for ( i = 0; i < size; ++i )
     334                 :            :                 {
     335         [ #  # ]:          0 :                 if ( data[d_ind] == ENVIRON_ESC )
     336                 :          0 :                         ++d_ind;
     337                 :            : 
     338                 :          0 :                 env[i] = data[d_ind];
     339                 :          0 :                 ++d_ind;
     340                 :            :                 }
     341                 :            : 
     342                 :          0 :         env[i] = '\0';
     343                 :            : 
     344                 :          0 :         data = d;
     345                 :          0 :         len -= size;
     346                 :            : 
     347                 :          0 :         return env;
     348                 :            :         }
     349                 :            : 
     350                 :          0 : void TelnetBinaryOption::SetActive(int is_active)
     351                 :            :         {
     352                 :          0 :         endp->SetBinaryMode(is_active);
     353                 :          0 :         active = is_active;
     354                 :          0 :         }
     355                 :            : 
     356                 :          0 : void TelnetBinaryOption::InconsistentOption(unsigned int /* type */)
     357                 :            :         {
     358                 :            :         // I don't know why, but this gets turned on redundantly -
     359                 :            :         // doesn't do any harm, so ignore it.  Example is
     360                 :            :         // in ex/redund-binary-opt.trace.
     361                 :          0 :         }
     362                 :            : 
     363                 :            : 
     364                 :          0 : NVT_Analyzer::NVT_Analyzer(Connection* conn, bool orig)
     365                 :          0 : : ContentLine_Analyzer(AnalyzerTag::NVT, conn, orig)
     366                 :            :         {
     367                 :          0 :         peer = 0;
     368                 :          0 :         is_suboption = last_was_IAC = pending_IAC = 0;
     369                 :          0 :         IAC_pos = 0;
     370                 :          0 :         num_options = 0;
     371                 :          0 :         authentication_has_been_accepted = encrypting_mode = binary_mode = 0;
     372                 :          0 :         auth_name = 0;
     373                 :          0 :         }
     374                 :            : 
     375                 :          0 : NVT_Analyzer::~NVT_Analyzer()
     376                 :            :         {
     377 [ #  # ][ #  # ]:          0 :         for ( int i = 0; i < num_options; ++i )
                 [ #  # ]
     378 [ #  # ][ #  # ]:          0 :                 delete options[i];
                 [ #  # ]
     379                 :            : 
     380 [ #  # ][ #  # ]:          0 :         delete [] auth_name;
                 [ #  # ]
     381 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     382                 :            : 
     383                 :          0 : TelnetOption* NVT_Analyzer::FindOption(unsigned int code)
     384                 :            :         {
     385                 :            :         int i;
     386         [ #  # ]:          0 :         for ( i = 0; i < num_options; ++i )
     387         [ #  # ]:          0 :                 if ( options[i]->Code() == code )
     388                 :          0 :                         return options[i];
     389                 :            : 
     390                 :          0 :         TelnetOption* opt = 0;
     391         [ #  # ]:          0 :         if ( i < NUM_TELNET_OPTIONS )
     392                 :            :                 { // Maybe we haven't created this option yet.
     393 [ #  #  #  #  # :          0 :                 switch ( code ) {
                      # ]
     394                 :            :                 case TELNET_OPTION_BINARY:
     395                 :          0 :                         opt = new TelnetBinaryOption(this);
     396                 :          0 :                         break;
     397                 :            : 
     398                 :            :                 case TELNET_OPTION_TERMINAL:
     399                 :          0 :                         opt = new TelnetTerminalOption(this);
     400                 :          0 :                         break;
     401                 :            : 
     402                 :            :                 case TELNET_OPTION_ENCRYPT:
     403                 :          0 :                         opt = new TelnetEncryptOption(this);
     404                 :          0 :                         break;
     405                 :            : 
     406                 :            :                 case TELNET_OPTION_AUTHENTICATE:
     407                 :          0 :                         opt = new TelnetAuthenticateOption(this);
     408                 :          0 :                         break;
     409                 :            : 
     410                 :            :                 case TELNET_OPTION_ENVIRON:
     411                 :          0 :                         opt = new TelnetEnvironmentOption(this);
     412                 :            :                         break;
     413                 :            :                 }
     414                 :            :                 }
     415                 :            : 
     416         [ #  # ]:          0 :         if ( opt )
     417                 :          0 :                 options[num_options++] = opt;
     418                 :            : 
     419                 :          0 :         return opt;
     420                 :            :         }
     421                 :            : 
     422                 :          0 : TelnetOption* NVT_Analyzer::FindPeerOption(unsigned int code)
     423                 :            :         {
     424         [ #  # ]:          0 :         assert(peer);
     425                 :          0 :         return peer->FindOption(code);
     426                 :            :         }
     427                 :            : 
     428                 :          0 : void NVT_Analyzer::AuthenticationAccepted()
     429                 :            :         {
     430                 :          0 :         authentication_has_been_accepted = 1;
     431                 :          0 :         Event(authentication_accepted, PeerAuthName());
     432                 :          0 :         }
     433                 :            : 
     434                 :          0 : void NVT_Analyzer::AuthenticationRejected()
     435                 :            :         {
     436                 :          0 :         authentication_has_been_accepted = 0;
     437                 :          0 :         Event(authentication_rejected, PeerAuthName());
     438                 :          0 :         }
     439                 :            : 
     440                 :          0 : const char* NVT_Analyzer::PeerAuthName() const
     441                 :            :         {
     442         [ #  # ]:          0 :         assert(peer);
     443                 :          0 :         return peer->AuthName();
     444                 :            :         }
     445                 :            : 
     446                 :          0 : void NVT_Analyzer::SetTerminal(const u_char* terminal, int len)
     447                 :            :         {
     448         [ #  # ]:          0 :         if ( login_terminal )
     449                 :            :                 {
     450                 :          0 :                 val_list* vl = new val_list;
     451                 :          0 :                 vl->append(BuildConnVal());
     452                 :          0 :                 vl->append(new StringVal(new BroString(terminal, len, 0)));
     453                 :            : 
     454                 :          0 :                 ConnectionEvent(login_terminal, vl);
     455                 :            :                 }
     456                 :          0 :         }
     457                 :            : 
     458                 :          0 : void NVT_Analyzer::SetEncrypting(int mode)
     459                 :            :         {
     460                 :          0 :         encrypting_mode = mode;
     461                 :          0 :         SetSkipDeliveries(mode);
     462         [ #  # ]:          0 :         if ( mode )
     463                 :          0 :                 Event(activating_encryption);
     464                 :          0 :         }
     465                 :            : 
     466                 :            : #define MAX_DELIVER_UNIT 128
     467                 :            : 
     468                 :          0 : void NVT_Analyzer::DoDeliver(int len, const u_char* data)
     469                 :            :         {
     470                 :            :         // This code is very similar to that for TCP_ContentLine.  We
     471                 :            :         // don't virtualize out the differences because some of them
     472                 :            :         // would require per-character function calls, too expensive.
     473         [ #  # ]:          0 :         if ( pending_IAC )
     474                 :            :                 {
     475                 :          0 :                 ScanOption(seq, len, data);
     476                 :          0 :                 return;
     477                 :            :                 }
     478                 :            : 
     479                 :            :         // Add data up to IAC or end.
     480         [ #  # ]:          0 :         for ( ; len > 0; --len, ++data )
     481                 :            :                 {
     482         [ #  # ]:          0 :                 if ( offset >= buf_len )
     483                 :          0 :                         InitBuffer(buf_len * 2);
     484                 :            : 
     485                 :          0 :                 int c = data[0];
     486                 :            : 
     487 [ #  # ][ #  # ]:          0 :                 if ( binary_mode && c != TELNET_IAC )
     488                 :          0 :                         c &= 0x7f;
     489                 :            : 
     490                 :            : #define EMIT_LINE \
     491                 :            :         { \
     492                 :            :         buf[offset] = '\0'; \
     493                 :            :         ForwardStream(offset, buf, IsOrig()); \
     494                 :            :         offset = 0; \
     495                 :            :         }
     496                 :            : 
     497   [ #  #  #  #  :          0 :                 switch ( c ) {
                      # ]
     498                 :            :                 case '\r':
     499         [ #  # ]:          0 :                         if ( CRLFAsEOL() & CR_as_EOL )
     500                 :          0 :                                 EMIT_LINE
     501                 :            :                         else
     502                 :          0 :                                 buf[offset++] = c;
     503                 :          0 :                         break;
     504                 :            : 
     505                 :            :                 case '\n':
     506         [ #  # ]:          0 :                         if ( last_char == '\r' )
     507                 :            :                                 {
     508         [ #  # ]:          0 :                                 if ( CRLFAsEOL() & CR_as_EOL )
     509                 :            :                                         // we already emited, skip
     510                 :            :                                         ;
     511                 :            :                                 else
     512                 :            :                                         {
     513                 :          0 :                                         --offset; // remove '\r'
     514                 :          0 :                                         EMIT_LINE
     515                 :            :                                         }
     516                 :            :                                 }
     517                 :            : 
     518         [ #  # ]:          0 :                         else if ( CRLFAsEOL() & LF_as_EOL )
     519                 :          0 :                                 EMIT_LINE
     520                 :            : 
     521                 :            :                         else
     522                 :            :                                 {
     523         [ #  # ]:          0 :                                 if ( Conn()->FlagEvent(SINGULAR_LF) )
     524                 :          0 :                                         Conn()->Weird("line_terminated_with_single_LF");
     525                 :          0 :                                 buf[offset++] = c;
     526                 :            :                                 }
     527                 :          0 :                         break;
     528                 :            : 
     529                 :            :                 case '\0':
     530         [ #  # ]:          0 :                         if ( last_char == '\r' )
     531                 :            :                                 // Allow a NUL just after a \r - Solaris
     532                 :            :                                 // Telnet servers generate these, and they
     533                 :            :                                 // appear harmless.
     534                 :            :                                 ;
     535                 :            : 
     536         [ #  # ]:          0 :                         else if ( flag_NULs )
     537                 :          0 :                                 CheckNUL();
     538                 :            : 
     539                 :            :                         else
     540                 :          0 :                                 buf[offset++] = c;
     541                 :          0 :                         break;
     542                 :            : 
     543                 :            :                 case TELNET_IAC:
     544                 :          0 :                         pending_IAC = 1;
     545                 :          0 :                         IAC_pos = offset;
     546                 :          0 :                         is_suboption = 0;
     547                 :          0 :                         buf[offset++] = c;
     548                 :          0 :                         ScanOption(seq, len - 1, data + 1);
     549                 :          0 :                         return;
     550                 :            : 
     551                 :            :                 default:
     552                 :          0 :                         buf[offset++] = c;
     553                 :            :                         break;
     554                 :            :                 }
     555                 :            : 
     556 [ #  # ][ #  # ]:          0 :                 if ( ! (CRLFAsEOL() & CR_as_EOL) &&
         [ #  # ][ #  # ]
                 [ #  # ]
     557                 :            :                      last_char == '\r' && c != '\n' && c != '\0' )
     558                 :            :                         {
     559         [ #  # ]:          0 :                         if ( Conn()->FlagEvent(SINGULAR_CR) )
     560                 :          0 :                                 Weird("line_terminated_with_single_CR");
     561                 :            :                         }
     562                 :            : 
     563                 :          0 :                 last_char = c;
     564                 :            :                 }
     565                 :            :         }
     566                 :            : 
     567                 :          0 : void NVT_Analyzer::ScanOption(int seq, int len, const u_char* data)
     568                 :            :         {
     569         [ #  # ]:          0 :         if ( len <= 0 )
     570                 :          0 :                 return;
     571                 :            : 
     572         [ #  # ]:          0 :         if ( IAC_pos == offset - 1 )
     573                 :            :                 { // All we've seen so far is the IAC.
     574                 :          0 :                 unsigned int code = data[0];
     575                 :            : 
     576         [ #  # ]:          0 :                 if ( code == TELNET_IAC )
     577                 :            :                         {
     578                 :            :                         // An escaped 255, throw away the second
     579                 :            :                         // instance and drop the IAC state.
     580                 :          0 :                         pending_IAC = 0;
     581                 :          0 :                         last_char = code;
     582                 :            :                         }
     583                 :            : 
     584         [ #  # ]:          0 :                 else if ( code == TELNET_OPT_SB )
     585                 :            :                         {
     586                 :          0 :                         is_suboption = 1;
     587                 :          0 :                         last_was_IAC = 0;
     588                 :          0 :                         buf[offset++] = code;
     589                 :            :                         }
     590                 :            : 
     591 [ #  # ][ #  # ]:          0 :                 else if ( IS_3_BYTE_OPTION(code) )
     592                 :            :                         {
     593                 :          0 :                         is_suboption = 0;
     594                 :          0 :                         buf[offset++] = code;
     595                 :            :                         }
     596                 :            : 
     597                 :            :                 else
     598                 :            :                         {
     599                 :            :                         // We've got the whole 2-byte option.
     600                 :          0 :                         SawOption(code);
     601                 :            : 
     602                 :            :                         // Throw it and the IAC away.
     603                 :          0 :                         --offset;
     604                 :          0 :                         pending_IAC = 0;
     605                 :            :                         }
     606                 :            : 
     607                 :            :                 // Recurse to munch on the remainder.
     608                 :          0 :                 DeliverStream(len - 1, data + 1, IsOrig());
     609                 :          0 :                 return;
     610                 :            :                 }
     611                 :            : 
     612         [ #  # ]:          0 :         if ( ! is_suboption )
     613                 :            :                 {
     614                 :            :                 // We now have the full 3-byte option.
     615                 :          0 :                 SawOption(u_char(buf[offset-1]), data[0]);
     616                 :            : 
     617                 :            :                 // Delete the option.
     618                 :          0 :                 offset -= 2;    // code + IAC
     619                 :          0 :                 pending_IAC = 0;
     620                 :            : 
     621                 :          0 :                 DeliverStream(len - 1, data + 1, IsOrig());
     622                 :          0 :                 return;
     623                 :            :                 }
     624                 :            : 
     625                 :            :         // A suboption.  Spin looking for end.
     626         [ #  # ]:          0 :         for ( ; len > 0; --len, ++data )
     627                 :            :                 {
     628                 :          0 :                 unsigned int code = data[0];
     629                 :            : 
     630         [ #  # ]:          0 :                 if ( last_was_IAC )
     631                 :            :                         {
     632                 :          0 :                         last_was_IAC = 0;
     633                 :            : 
     634         [ #  # ]:          0 :                         if ( code == TELNET_IAC )
     635                 :            :                                 {
     636                 :            :                                 // This is an escaped IAC, eat
     637                 :            :                                 // the second copy.
     638                 :          0 :                                 continue;
     639                 :            :                                 }
     640                 :            : 
     641         [ #  # ]:          0 :                         if ( code != TELNET_OPT_SE )
     642                 :            :                                 // BSD Telnet treats this case as terminating
     643                 :            :                                 // the suboption, so that's what we do here
     644                 :            :                                 // too.  Below we make sure to munch on the
     645                 :            :                                 // new IAC.
     646                 :          0 :                                 BadOptionTermination(code);
     647                 :            : 
     648                 :          0 :                         int opt_start = IAC_pos + 2;
     649                 :          0 :                         int opt_stop = offset - 1;
     650                 :          0 :                         int opt_len = opt_stop - opt_start;
     651                 :          0 :                         SawSubOption((const char*)&buf[opt_start], opt_len);
     652                 :            : 
     653                 :            :                         // Delete suboption.
     654                 :          0 :                         offset = IAC_pos;
     655                 :          0 :                         pending_IAC = is_suboption = 0;
     656                 :            : 
     657         [ #  # ]:          0 :                         if ( code == TELNET_OPT_SE )
     658                 :          0 :                                 DeliverStream(len - 1, data + 1, IsOrig());
     659                 :            :                         else
     660                 :            :                                 {
     661                 :            :                                 // Munch on the new (broken) option.
     662                 :          0 :                                 pending_IAC = 1;
     663                 :          0 :                                 IAC_pos = offset;
     664                 :          0 :                                 buf[offset++] = TELNET_IAC;
     665                 :          0 :                                 DeliverStream(len, data, IsOrig());
     666                 :            :                                 }
     667                 :          0 :                         return;
     668                 :            :                         }
     669                 :            : 
     670                 :            :                 else
     671                 :            :                         {
     672                 :          0 :                         buf[offset++] = code;
     673                 :          0 :                         last_was_IAC = (code == TELNET_IAC);
     674                 :            :                         }
     675                 :            :                 }
     676                 :            :         }
     677                 :            : 
     678                 :          0 : void NVT_Analyzer::SawOption(unsigned int /* code */)
     679                 :            :         {
     680                 :          0 :         }
     681                 :            : 
     682                 :          0 : void NVT_Analyzer::SawOption(unsigned int code, unsigned int subcode)
     683                 :            :         {
     684                 :          0 :         TelnetOption* opt = FindOption(subcode);
     685         [ #  # ]:          0 :         if ( opt )
     686                 :          0 :                 opt->RecvOption(code);
     687                 :          0 :         }
     688                 :            : 
     689                 :          0 : void NVT_Analyzer::SawSubOption(const char* subopt, int len)
     690                 :            :         {
     691                 :          0 :         unsigned int subcode = u_char(subopt[0]);
     692                 :            : 
     693                 :          0 :         ++subopt;
     694                 :          0 :         --len;
     695                 :            : 
     696                 :          0 :         TelnetOption* opt = FindOption(subcode);
     697         [ #  # ]:          0 :         if ( opt )
     698                 :          0 :                 opt->RecvSubOption((u_char*) subopt, len);
     699                 :          0 :         }
     700                 :            : 
     701                 :          0 : void NVT_Analyzer::BadOptionTermination(unsigned int /* code */)
     702                 :            :         {
     703                 :          0 :         Event(bad_option_termination);
     704 [ +  - ][ +  - ]:          6 :         }
     705                 :          3 : 

Generated by: LCOV version 1.8