LCOV - code coverage report
Current view: top level - src - SSLv2.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 372 0.5 %
Date: 2010-12-13 Functions: 2 23 8.7 %
Branches: 2 323 0.6 %

           Branch data     Line data    Source code
       1                 :            : // $Id: SSLv2.cc 5988 2008-07-19 07:02:12Z vern $
       2                 :            : 
       3                 :            : #include "SSLv2.h"
       4                 :            : #include "SSLv3.h"
       5                 :            : 
       6                 :            : // --- Initalization of static variables --------------------------------------
       7                 :            : 
       8                 :            : uint SSLv2_Interpreter::totalConnections = 0;
       9                 :            : uint SSLv2_Interpreter::analyzedConnections = 0;
      10                 :            : uint SSLv2_Interpreter::openedConnections = 0;
      11                 :            : uint SSLv2_Interpreter::failedConnections = 0;
      12                 :            : uint SSLv2_Interpreter::weirdConnections = 0;
      13                 :            : uint SSLv2_Interpreter::totalRecords = 0;
      14                 :            : uint SSLv2_Interpreter::clientHelloRecords = 0;
      15                 :            : uint SSLv2_Interpreter::serverHelloRecords = 0;
      16                 :            : uint SSLv2_Interpreter::clientMasterKeyRecords = 0;
      17                 :            : uint SSLv2_Interpreter::errorRecords = 0;
      18                 :            : 
      19                 :            : 
      20                 :            : // --- SSLv2_Interpreter -------------------------------------------------------
      21                 :            : 
      22                 :            : /*!
      23                 :            :  * The Constructor.
      24                 :            :  *
      25                 :            :  * \param proxy Pointer to the SSLProxy_Analyzer who created this instance.
      26                 :            :  */
      27                 :          0 : SSLv2_Interpreter::SSLv2_Interpreter(SSLProxy_Analyzer* proxy)
      28                 :          0 : : SSL_Interpreter(proxy)
      29                 :            :         {
      30                 :          0 :         ++totalConnections;
      31                 :          0 :         records = 0;
      32                 :          0 :         bAnalyzedCounted = false;
      33                 :          0 :         connState = START;
      34                 :            : 
      35                 :          0 :         pServerCipherSpecs = 0;
      36                 :          0 :         pClientCipherSpecs = 0;
      37                 :          0 :         bClientWantsCachedSession = false;
      38                 :          0 :         usedCipherSpec = (SSLv2_CipherSpec) 0;
      39                 :            : 
      40                 :          0 :         pConnectionId = 0;
      41                 :          0 :         pChallenge = 0;
      42                 :          0 :         pSessionId = 0;
      43                 :          0 :         pMasterClearKey = 0;
      44                 :          0 :         pMasterEncryptedKey = 0;
      45                 :          0 :         pClientReadKey = 0;
      46                 :          0 :         pServerReadKey = 0;
      47                 :          0 :         }
      48                 :            : 
      49                 :            : /*!
      50                 :            :  * The Destructor.
      51                 :            :  */
      52                 :          0 : SSLv2_Interpreter::~SSLv2_Interpreter()
      53                 :            :         {
      54 [ #  # ][ #  # ]:          0 :         if ( connState != CLIENT_MASTERKEY_SEEN &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      55                 :            :              connState != CACHED_SESSION &&
      56                 :            :              connState != START &&      // we only complain if we saw some data
      57                 :            :              connState != ERROR_SEEN )
      58                 :          0 :                 ++failedConnections;
      59                 :            : 
      60 [ #  # ][ #  # ]:          0 :         if ( connState != CLIENT_MASTERKEY_SEEN && connState != CACHED_SESSION )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      61                 :          0 :                 ++weirdConnections;
      62                 :            : 
      63 [ #  # ][ #  # ]:          0 :         delete pServerCipherSpecs;
                 [ #  # ]
      64 [ #  # ][ #  # ]:          0 :         delete pClientCipherSpecs;
                 [ #  # ]
      65 [ #  # ][ #  # ]:          0 :         delete pConnectionId;
                 [ #  # ]
      66 [ #  # ][ #  # ]:          0 :         delete pChallenge;
                 [ #  # ]
      67 [ #  # ][ #  # ]:          0 :         delete pSessionId;
                 [ #  # ]
      68 [ #  # ][ #  # ]:          0 :         delete pMasterClearKey;
                 [ #  # ]
      69 [ #  # ][ #  # ]:          0 :         delete pMasterEncryptedKey;
                 [ #  # ]
      70 [ #  # ][ #  # ]:          0 :         delete pClientReadKey;
                 [ #  # ]
      71 [ #  # ][ #  # ]:          0 :         delete pServerReadKey;
                 [ #  # ]
      72 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
      73                 :            : 
      74                 :            : /*!
      75                 :            :  * This method implements SSL_Interpreter::BuildInterpreterEndpoints()
      76                 :            :  */
      77                 :          0 : void SSLv2_Interpreter::BuildInterpreterEndpoints()
      78                 :            :         {
      79                 :          0 :         orig = new SSLv2_Endpoint(this, 1);
      80                 :          0 :         resp = new SSLv2_Endpoint(this, 0);
      81                 :          0 :         }
      82                 :            : 
      83                 :            : /*!
      84                 :            :  * This method prints some counters.
      85                 :            :  */
      86                 :          0 : void SSLv2_Interpreter::printStats()
      87                 :            :         {
      88                 :          0 :         printf("SSLv2:\n");
      89                 :          0 :         printf("totalConnections    = %u\n", totalConnections);
      90                 :          0 :         printf("analyzedConnections = %u\n", analyzedConnections);
      91                 :          0 :         printf("openedConnections   = %u\n", openedConnections);
      92                 :          0 :         printf("failedConnections   = %u\n", failedConnections);
      93                 :          0 :         printf("weirdConnections   = %u\n", weirdConnections);
      94                 :            : 
      95                 :          0 :         printf("totalRecords            = %u\n", totalRecords);
      96                 :          0 :         printf("clientHelloRecords      = %u\n", clientHelloRecords);
      97                 :          0 :         printf("serverHelloRecords      = %u\n", serverHelloRecords);
      98                 :          0 :         printf("clientMasterKeyRecords  = %u\n", clientMasterKeyRecords);
      99                 :          0 :         printf("errorRecords            = %u\n", errorRecords);
     100                 :            : 
     101                 :          0 :         printf("SSL_RecordBuilder::maxAllocCount     = %u\n", SSL_RecordBuilder::maxAllocCount);
     102                 :          0 :         printf("SSL_RecordBuilder::maxFragmentCount  = %u\n", SSL_RecordBuilder::maxFragmentCount);
     103                 :          0 :         printf("SSL_RecordBuilder::fragmentedHeaders = %u\n", SSL_RecordBuilder::fragmentedHeaders);
     104                 :          0 :         }
     105                 :            : 
     106                 :            : /*!
     107                 :            :  * \return the current state of the ssl connection
     108                 :            :  */
     109                 :          0 : SSLv2_States SSLv2_Interpreter::ConnState()
     110                 :            :         {
     111                 :          0 :         return connState;
     112                 :            :         }
     113                 :            : 
     114                 :            : /*!
     115                 :            :  * This method is called by SSLv2_Endpoint::Deliver(). It is the main entry
     116                 :            :  * point of this class. The header of the given SSLV2 record is analyzed and
     117                 :            :  * its contents are then passed to the corresponding analyzer method. After
     118                 :            :  * the record has been analyzed, the ssl connection state is updated.
     119                 :            :  *
     120                 :            :  * \param s Pointer to the endpoint which sent the record
     121                 :            :  * \param length length of SSLv2 record
     122                 :            :  * \param data pointer to SSLv2 record to analyze
     123                 :            :  */
     124                 :            : void SSLv2_Interpreter::NewSSLRecord(SSL_InterpreterEndpoint* s,
     125                 :          0 :                                         int length, const u_char* data)
     126                 :            :         {
     127                 :          0 :         ++records;
     128                 :          0 :         ++totalRecords;
     129                 :            : 
     130         [ #  # ]:          0 :         if ( ! bAnalyzedCounted )
     131                 :            :                 {
     132                 :          0 :                 ++analyzedConnections;
     133                 :          0 :                 bAnalyzedCounted = true;
     134                 :            :                 }
     135                 :            : 
     136                 :            :         // We should see a maximum of 4 cleartext records.
     137         [ #  # ]:          0 :         if ( records == 5 )
     138                 :            :                 { // so this should never happen
     139                 :          0 :                 Weird("SSLv2: Saw more than 4 records, skipping connection...");
     140                 :          0 :                 proxy->SetSkip(1);
     141                 :          0 :                 return;
     142                 :            :                 }
     143                 :            : 
     144                 :            :         // SSLv2 record header analysis
     145                 :          0 :         uint32 recordLength = 0; // data length of SSLv2 record
     146                 :          0 :         bool isEscape = false;
     147                 :          0 :         uint8 padding = 0;
     148                 :            :         const u_char* contents;
     149                 :            : 
     150         [ #  # ]:          0 :         if ( (data[0] & 0x80) > 0 )
     151                 :            :                 { // we have a two-byte record header
     152                 :          0 :                 recordLength = ((data[0] & 0x7f) << 8) | data[1];
     153                 :          0 :                 contents = data + 2;
     154         [ #  # ]:          0 :                 if (  recordLength + 2 != uint32(length)  )
     155                 :            :                         {
     156                 :            :                         // This should never happen, otherwise
     157                 :            :                         // we have a bug in the SSL_RecordBuilder.
     158                 :          0 :                         Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
     159                 :          0 :                         connState = ERROR_REQUIRED;
     160                 :          0 :                         proxy->SetSkip(1);
     161                 :          0 :                         return;
     162                 :            :                         }
     163                 :            :                 }
     164                 :            :         else
     165                 :            :                 { // We have a three-byte record header.
     166                 :          0 :                 recordLength = ((data[0] & 0x3f) << 8) | data[1];
     167                 :          0 :                 isEscape = (data[0] & 0x40) != 0;
     168                 :          0 :                 padding = data[2];
     169                 :          0 :                 contents = data + 3;
     170         [ #  # ]:          0 :                 if ( recordLength + 3 != uint32(length) )
     171                 :            :                         {
     172                 :            :                         // This should never happen, otherwise
     173                 :            :                         // we have a bug in the SSL_RecordBuilder.
     174                 :          0 :                         Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
     175                 :          0 :                         connState = ERROR_REQUIRED;
     176                 :          0 :                         proxy->SetSkip(1);
     177                 :          0 :                         return;
     178                 :            :                         }
     179                 :            : 
     180 [ #  # ][ #  # ]:          0 :                 if ( padding == 0 && ! isEscape )
     181                 :          0 :                         Weird("SSLv2: 3 Byte record header, but no escape, no padding!");
     182                 :            :                 }
     183                 :            : 
     184         [ #  # ]:          0 :         if ( recordLength == 0 )
     185                 :            :                 {
     186                 :          0 :                 Weird("SSLv2: Record length is zero (no record data)!");
     187                 :          0 :                 return;
     188                 :            :                 }
     189                 :            : 
     190         [ #  # ]:          0 :         if ( isEscape )
     191                 :          0 :                 Weird("SSLv2: Record has escape bit set (security escape)!");
     192                 :            : 
     193 [ #  # ][ #  # ]:          0 :         if  ( padding > 0 && connState != CACHED_SESSION &&
                 [ #  # ]
     194                 :            :               connState != CLIENT_MASTERKEY_SEEN )
     195                 :          0 :                 Weird("SSLv2 record with padding > 0 in cleartext!");
     196                 :            : 
     197                 :            :         // MISSING:
     198                 :            :         // A final consistency check is done when a block cipher is used
     199                 :            :         // and the protocol is using encryption. The amount of data present
     200                 :            :         // in a record (RECORD-LENGTH))must be a multiple of the cipher's
     201                 :            :         // block size.  If the received record is not a multiple of the
     202                 :            :         // cipher's block size then the record is considered damaged, and it
     203                 :            :         // is to be treated as if an "I/O Error" had occurred (i.e. an
     204                 :            :         // unrecoverable error is asserted and the connection is closed).
     205                 :            : 
     206 [ #  #  #  #  # :          0 :         switch ( connState ) {
                #  #  # ]
     207                 :            :         case START:
     208                 :            :                 // Only CLIENT-HELLLOs allowed here.
     209         [ #  # ]:          0 :                 if ( contents[0] != SSLv2_MT_CLIENT_HELLO )
     210                 :            :                         {
     211                 :          0 :                         Weird("SSLv2: First packet is not a CLIENT-HELLO!");
     212                 :          0 :                         analyzeRecord(s, recordLength, contents);
     213                 :          0 :                         connState = ERROR_REQUIRED;
     214                 :            :                         }
     215                 :            :                 else
     216                 :          0 :                         connState = ClientHelloRecord(s, recordLength, contents);
     217                 :          0 :                 break;
     218                 :            : 
     219                 :            :         case CLIENT_HELLO_SEEN:
     220                 :            :                 // Only SERVER-HELLOs or ERRORs allowed here.
     221         [ #  # ]:          0 :                 if ( contents[0] == SSLv2_MT_SERVER_HELLO )
     222                 :          0 :                         connState = ServerHelloRecord(s, recordLength, contents);
     223         [ #  # ]:          0 :                 else if ( contents[0] == SSLv2_MT_ERROR )
     224                 :          0 :                         connState = ErrorRecord(s, recordLength, contents);
     225                 :            :                 else
     226                 :            :                         {
     227                 :          0 :                         Weird("SSLv2: State violation in CLIENT_HELLO_SEEN!");
     228                 :          0 :                         analyzeRecord(s, recordLength, contents);
     229                 :          0 :                         connState = ERROR_REQUIRED;
     230                 :            :                         }
     231                 :          0 :                 break;
     232                 :            : 
     233                 :            :         case NEW_SESSION:
     234                 :            :                 // We expect a client master key.
     235         [ #  # ]:          0 :                 if ( contents[0] == SSLv2_MT_CLIENT_MASTER_KEY )
     236                 :          0 :                         connState = ClientMasterKeyRecord(s, recordLength, contents);
     237         [ #  # ]:          0 :                 else if ( contents[0] == SSLv2_MT_ERROR )
     238                 :          0 :                         connState = ErrorRecord(s, recordLength, contents);
     239                 :            :                 else
     240                 :            :                         {
     241                 :          0 :                         Weird("SSLv2: State violation in NEW_SESSION or encrypted record!");
     242                 :          0 :                         analyzeRecord(s, recordLength, contents);
     243                 :          0 :                         connState = ERROR_REQUIRED;
     244                 :            :                         }
     245                 :            : 
     246         [ #  # ]:          0 :                 delete pServerCipherSpecs;
     247                 :          0 :                 pServerCipherSpecs = 0;
     248                 :          0 :                 break;
     249                 :            : 
     250                 :            :         case CACHED_SESSION:
     251         [ #  # ]:          0 :                 delete pServerCipherSpecs;
     252                 :          0 :                 pServerCipherSpecs = 0;
     253                 :            :                 // No break here.
     254                 :            : 
     255                 :            :         case CLIENT_MASTERKEY_SEEN:
     256                 :            :                 // If no error record, no further analysis.
     257 [ #  # ][ #  # ]:          0 :                 if ( contents[0] == SSLv2_MT_ERROR &&
     258                 :            :                      recordLength == SSLv2_ERROR_RECORD_SIZE )
     259                 :          0 :                         connState = ErrorRecord(s, recordLength, contents);
     260                 :            :                 else
     261                 :            :                         {
     262                 :            :                         // So we finished the cleartext handshake.
     263                 :            :                         // Skip all further data.
     264                 :            : 
     265                 :          0 :                         proxy->SetSkip(1);
     266                 :          0 :                         ++openedConnections;
     267                 :            :                         }
     268                 :          0 :                 break;
     269                 :            : 
     270                 :            :         case ERROR_REQUIRED:
     271         [ #  # ]:          0 :                 if ( contents[0] == SSLv2_MT_ERROR )
     272                 :          0 :                         connState = ErrorRecord(s, recordLength, contents);
     273                 :            :                 else
     274                 :            :                         {
     275                 :            :                         // We lost tracking: this should not happen.
     276                 :          0 :                         Weird("SSLv2: State inconsistency in ERROR_REQUIRED (lost tracking!)!");
     277                 :          0 :                         analyzeRecord(s, recordLength, contents);
     278                 :          0 :                         connState = ERROR_REQUIRED;
     279                 :            :                         }
     280                 :          0 :                 break;
     281                 :            : 
     282                 :            :         case ERROR_SEEN:
     283                 :            :                 // We don't have recoverable errors in cleartext phase,
     284                 :            :                 // so we shouldn't see anymore packets.
     285                 :          0 :                 Weird("SSLv2: Traffic after error record!");
     286                 :          0 :                 analyzeRecord(s, recordLength, contents);
     287                 :          0 :                 break;
     288                 :            : 
     289                 :            :         default:
     290                 :          0 :                 internal_error("SSLv2: unknown state");
     291                 :            :                 break;
     292                 :            :         }
     293                 :            :         }
     294                 :            : 
     295                 :            : /*!
     296                 :            :  * This method is called whenever the connection tracking failed. It calls
     297                 :            :  * the corresponding analyzer method for the given SSLv2 record, but does not
     298                 :            :  * update the ssl connection state.
     299                 :            :  *
     300                 :            :  * \param s Pointer to the endpoint which sent the record
     301                 :            :  * \param length length of SSLv2 record
     302                 :            :  * \param data pointer to SSLv2 record to analyze
     303                 :            :  */
     304                 :            : void SSLv2_Interpreter::analyzeRecord(SSL_InterpreterEndpoint* s,
     305                 :          0 :                                         int length, const u_char* data)
     306                 :            :         {
     307 [ #  #  #  #  # :          0 :         switch ( data[0] ) {
                      # ]
     308                 :            :         case SSLv2_MT_ERROR:
     309                 :          0 :                 ErrorRecord(s, length, data);
     310                 :          0 :                 break;
     311                 :            : 
     312                 :            :         case SSLv2_MT_CLIENT_HELLO:
     313                 :          0 :                 ClientHelloRecord(s, length, data);
     314                 :          0 :                 break;
     315                 :            : 
     316                 :            :         case SSLv2_MT_CLIENT_MASTER_KEY:
     317                 :          0 :                 ClientMasterKeyRecord(s, length, data);
     318                 :          0 :                 break;
     319                 :            : 
     320                 :            :         case SSLv2_MT_SERVER_HELLO:
     321                 :          0 :                 ServerHelloRecord(s, length, data);
     322                 :          0 :                 break;
     323                 :            : 
     324                 :            :         case SSLv2_MT_CLIENT_FINISHED:
     325                 :            :         case SSLv2_MT_SERVER_VERIFY:
     326                 :            :         case SSLv2_MT_SERVER_FINISHED:
     327                 :            :         case SSLv2_MT_REQUEST_CERTIFICATE:
     328                 :            :         case SSLv2_MT_CLIENT_CERTIFICATE:
     329                 :          0 :                 Weird("SSLv2: Encrypted record type seems to be in cleartext");
     330                 :          0 :                 break;
     331                 :            : 
     332                 :            :         default:
     333                 :            :                 // Unknown record type.
     334                 :          0 :                 Weird("SSLv2: Unknown record type or encrypted record");
     335                 :            :                 break;
     336                 :            :         }
     337                 :          0 :         }
     338                 :            : 
     339                 :            : /*!
     340                 :            :  * This method analyses a SSLv2 CLIENT-HELLO record.
     341                 :            :  *
     342                 :            :  * \param s Pointer to the endpoint which sent the record
     343                 :            :  * \param length length of SSLv2 CLIENT-HELLO record
     344                 :            :  * \param data pointer to SSLv2 CLIENT-HELLO record to analyze
     345                 :            :  *
     346                 :            :  * \return the updated state of the current ssl connection
     347                 :            :  */
     348                 :            : SSLv2_States SSLv2_Interpreter::ClientHelloRecord(SSL_InterpreterEndpoint* s,
     349                 :          0 :                                         int recordLength, const u_char* recordData)
     350                 :            :         {
     351                 :            :         // This method gets the record's data (without the header).
     352                 :          0 :         ++clientHelloRecords;
     353                 :            : 
     354         [ #  # ]:          0 :         if ( s != orig )
     355                 :          0 :                 Weird("SSLv2: CLIENT-HELLO record from server!");
     356                 :            : 
     357                 :            :         // There should not be any pending data in the SSLv2 reassembler,
     358                 :            :         // because the client should wait for a server response.
     359         [ #  # ]:          0 :         if ( ((SSLv2_Endpoint*) s)->isDataPending() )
     360                 :          0 :                 Weird("SSLv2: Pending data in SSL_RecordBuilder after CLIENT-HELLO!");
     361                 :            : 
     362                 :            :         // Client hello minimum header size check.
     363         [ #  # ]:          0 :         if ( recordLength < SSLv2_CLIENT_HELLO_HEADER_SIZE )
     364                 :            :                 {
     365                 :          0 :                 Weird("SSLv2: CLIENT-HELLO is too small!");
     366                 :          0 :                 return ERROR_REQUIRED;
     367                 :            :                 }
     368                 :            : 
     369                 :            :         // Extract the data of the client hello header.
     370                 :            :         SSLv2_ClientHelloHeader ch;
     371                 :          0 :         ch.clientVersion = uint16(recordData[1] << 8) | recordData[2];
     372                 :          0 :         ch.cipherSpecLength = uint16(recordData[3] << 8) | recordData[4];
     373                 :          0 :         ch.sessionIdLength = uint16(recordData[5] << 8) | recordData[6];
     374                 :          0 :         ch.challengeLength = uint16(recordData[7] << 8) | recordData[8];
     375                 :            : 
     376 [ #  # ][ #  # ]:          0 :         if ( ch.clientVersion != SSLProxy_Analyzer::SSLv20 &&
                 [ #  # ]
     377                 :            :              ch.clientVersion != SSLProxy_Analyzer::SSLv30 &&
     378                 :            :              ch.clientVersion != SSLProxy_Analyzer::SSLv31 )
     379                 :            :                 {
     380                 :          0 :                 Weird("SSLv2: Unsupported SSL-Version in CLIENT-HELLO");
     381                 :          0 :                 return ERROR_REQUIRED;
     382                 :            :                 }
     383                 :            : 
     384         [ #  # ]:          0 :         if ( ch.challengeLength + ch.cipherSpecLength + ch.sessionIdLength +
     385                 :            :              SSLv2_CLIENT_HELLO_HEADER_SIZE != recordLength )
     386                 :            :                 {
     387                 :          0 :                 Weird("SSLv2: Size inconsistency in CLIENT-HELLO");
     388                 :          0 :                 return ERROR_REQUIRED;
     389                 :            :                 }
     390                 :            : 
     391                 :            :         // The CIPHER-SPECS-LENGTH must be > 0 and a multiple of 3.
     392 [ #  # ][ #  # ]:          0 :         if ( ch.cipherSpecLength == 0 || ch.cipherSpecLength % 3 != 0 )
     393                 :            :                 {
     394                 :          0 :                 Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in CLIENT-HELLO.");
     395                 :          0 :                 return ERROR_REQUIRED;
     396                 :            :                 }
     397                 :            : 
     398                 :            :         // The SESSION-ID-LENGTH must either be zero or 16.
     399 [ #  # ][ #  # ]:          0 :         if ( ch.sessionIdLength != 0 && ch.sessionIdLength != 16 )
     400                 :          0 :                 Weird("SSLv2: Nonconform SESSION-ID-LENGTH in CLIENT-HELLO.");
     401                 :            : 
     402 [ #  # ][ #  # ]:          0 :         if ( (ch.challengeLength < 16) || (ch.challengeLength > 32))
     403                 :          0 :                 Weird("SSLv2: Nonconform CHALLENGE-LENGTH in CLIENT-HELLO.");
     404                 :            : 
     405                 :          0 :         const u_char* ptr = recordData;
     406                 :          0 :         ptr += SSLv2_CLIENT_HELLO_HEADER_SIZE + ch.cipherSpecLength;
     407                 :            : 
     408                 :          0 :         pSessionId = new SSL_DataBlock(ptr, ch.sessionIdLength);
     409                 :            : 
     410                 :            :         // If decrypting, store the challenge.
     411   [ #  #  #  # ]:          0 :         if ( ssl_store_key_material && ch.challengeLength <= 32 )
     412                 :          0 :                 pChallenge = new SSL_DataBlock(ptr, ch.challengeLength);
     413                 :            : 
     414                 :          0 :         bClientWantsCachedSession = ch.sessionIdLength != 0;
     415                 :            : 
     416                 :            :         TableVal* currentCipherSuites =
     417                 :            :                 analyzeCiphers(s, ch.cipherSpecLength,
     418                 :          0 :                         recordData + SSLv2_CLIENT_HELLO_HEADER_SIZE);
     419                 :            : 
     420                 :          0 :         fire_ssl_conn_attempt(ch.clientVersion, currentCipherSuites);
     421                 :            : 
     422                 :          0 :         return CLIENT_HELLO_SEEN;
     423                 :            :         }
     424                 :            : 
     425                 :            : /*!
     426                 :            :  * This method analyses a SSLv2 SERVER-HELLO record.
     427                 :            :  *
     428                 :            :  * \param s Pointer to the endpoint which sent the record
     429                 :            :  * \param length length of SSLv2 SERVER-HELLO record
     430                 :            :  * \param data pointer to SSLv2 SERVER-HELLO record to analyze
     431                 :            :  *
     432                 :            :  * \return the updated state of the current ssl connection
     433                 :            :  */
     434                 :            : SSLv2_States SSLv2_Interpreter::ServerHelloRecord(SSL_InterpreterEndpoint* s,
     435                 :          0 :                                         int recordLength, const u_char* recordData)
     436                 :            :         {
     437                 :          0 :         ++serverHelloRecords;
     438                 :          0 :         TableVal* currentCipherSuites = NULL;
     439                 :            : 
     440         [ #  # ]:          0 :         if ( s != resp )
     441                 :          0 :                 Weird("SSLv2: SERVER-HELLO from client!");
     442                 :            : 
     443         [ #  # ]:          0 :         if ( recordLength < SSLv2_SERVER_HELLO_HEADER_SIZE )
     444                 :            :                 {
     445                 :          0 :                 Weird("SSLv2: SERVER-HELLO is too small!");
     446                 :          0 :                 return ERROR_REQUIRED;
     447                 :            :                 }
     448                 :            : 
     449                 :            :         // Extract the data of the client hello header.
     450                 :            :         SSLv2_ServerHelloHeader sh;
     451                 :          0 :         sh.sessionIdHit = recordData[1];
     452                 :          0 :         sh.certificateType = recordData[2];
     453                 :          0 :         sh.serverVersion = uint16(recordData[3] << 8) | recordData[4];
     454                 :          0 :         sh.certificateLength = uint16(recordData[5] << 8) | recordData[6];
     455                 :          0 :         sh.cipherSpecLength = uint16(recordData[7] << 8) | recordData[8];
     456                 :          0 :         sh.connectionIdLength = uint16(recordData[9] << 8) | recordData[10];
     457                 :            : 
     458         [ #  # ]:          0 :         if ( sh.serverVersion != SSLProxy_Analyzer::SSLv20 )
     459                 :            :                 {
     460                 :          0 :                 Weird("SSLv2: Unsupported SSL-Version in SERVER-HELLO");
     461                 :          0 :                 return ERROR_REQUIRED;
     462                 :            :                 }
     463                 :            : 
     464         [ #  # ]:          0 :         if ( sh.certificateLength + sh.cipherSpecLength +
     465                 :            :              sh.connectionIdLength +
     466                 :            :              SSLv2_SERVER_HELLO_HEADER_SIZE != recordLength )
     467                 :            :                 {
     468                 :          0 :                 Weird("SSLv2: Size inconsistency in SERVER-HELLO");
     469                 :          0 :                 return ERROR_REQUIRED;
     470                 :            :                 }
     471                 :            : 
     472                 :            :         // The length of the CONNECTION-ID must be between 16 and 32 bytes.
     473 [ #  # ][ #  # ]:          0 :         if ( sh.connectionIdLength < 16 || sh.connectionIdLength > 32 )
     474                 :          0 :                 Weird("SSLv2: Nonconform CONNECTION-ID-LENGTH in SERVER-HELLO");
     475                 :            : 
     476                 :            :         // If decrypting, store the connection ID.
     477 [ #  # ][ #  # ]:          0 :         if ( ssl_store_key_material && sh.connectionIdLength <= 32 )
     478                 :            :                 {
     479                 :          0 :                 const u_char* ptr = recordData;
     480                 :            : 
     481                 :            :                 ptr += SSLv2_SERVER_HELLO_HEADER_SIZE + sh.cipherSpecLength +
     482                 :          0 :                        sh.certificateLength;
     483                 :            : 
     484                 :          0 :                 pConnectionId = new SSL_DataBlock(ptr, sh.connectionIdLength);
     485                 :            :                 }
     486                 :            : 
     487         [ #  # ]:          0 :         if  ( sh.sessionIdHit == 0  )
     488                 :            :                 {
     489                 :            :                 // Generating reusing-connection event.
     490                 :          0 :                 EventHandlerPtr event = ssl_session_insertion;
     491                 :            : 
     492         [ #  # ]:          0 :                 if ( event )
     493                 :            :                         {
     494                 :            :                         TableVal* sessionIDTable =
     495                 :            :                                 MakeSessionID(
     496                 :            :                                         recordData +
     497                 :            :                                                 SSLv2_SERVER_HELLO_HEADER_SIZE +
     498                 :            :                                                 sh.certificateLength +
     499                 :            :                                                 sh.cipherSpecLength,
     500                 :          0 :                                         sh.connectionIdLength);
     501                 :            : 
     502                 :          0 :                         val_list* vl = new val_list;
     503                 :          0 :                         vl->append(proxy->BuildConnVal());
     504                 :          0 :                         vl->append(sessionIDTable);
     505                 :            : 
     506                 :          0 :                         proxy->ConnectionEvent(ssl_session_insertion, vl);
     507                 :            :                         }
     508                 :            :                 }
     509                 :            : 
     510                 :            :         SSLv2_States nextState;
     511                 :            : 
     512         [ #  # ]:          0 :         if ( sh.sessionIdHit != 0 )
     513                 :            :                 { // we're using a cached session
     514                 :            : 
     515                 :            :                 // There should not be any pending data in the SSLv2
     516                 :            :                 // reassembler, because the server should wait for a
     517                 :            :                 // client response.
     518                 :          0 :                 if ( ((SSLv2_Endpoint*) s)->isDataPending() )
     519                 :            :                         {
     520                 :            :                         // But turns out some SSL Implementations do this
     521                 :            :                         // when using a cached session.
     522                 :            :                         }
     523                 :            : 
     524                 :            :                 // Consistency check for SESSION-ID-HIT.
     525         [ #  # ]:          0 :                 if ( ! bClientWantsCachedSession )
     526                 :          0 :                         Weird("SSLv2: SESSION-ID hit in SERVER-HELLO, but no SESSION-ID in CLIENT-HELLO!");
     527                 :            : 
     528                 :            :                 // If the SESSION-ID-HIT flag is non-zero then the
     529                 :            :                 // CERTIFICATE-TYPE, CERTIFICATE-LENGTH and
     530                 :            :                 // CIPHER-SPECS-LENGTH fields will be zero.
     531 [ #  # ][ #  # ]:          0 :                 if ( sh.certificateType != 0 || sh.certificateLength != 0 ||
                 [ #  # ]
     532                 :            :                      sh.cipherSpecLength != 0 )
     533                 :          0 :                         Weird("SSLv2: SESSION-ID-HIT, but session data in SERVER-HELLO");
     534                 :            : 
     535                 :            :                 // Generate reusing-connection event.
     536         [ #  # ]:          0 :                 if ( pSessionId )
     537                 :            :                         {
     538                 :          0 :                         fire_ssl_conn_reused(pSessionId);
     539         [ #  # ]:          0 :                         delete pSessionId;
     540                 :          0 :                         pSessionId = 0;
     541                 :            :                         }
     542                 :            : 
     543                 :          0 :                 nextState = CACHED_SESSION;
     544                 :            :                 }
     545                 :            :         else
     546                 :            :                 { // we're starting a new session
     547                 :            : 
     548                 :            :                 // There should not be any pending data in the SSLv2
     549                 :            :                 // reassembler, because the server should wait for
     550                 :            :                 // a client response.
     551         [ #  # ]:          0 :                 if ( ((SSLv2_Endpoint*) s)->isDataPending() )
     552                 :          0 :                         Weird("SSLv2: Pending data in SSL_RecordBuilder after SERVER-HELLO (new session)!");
     553                 :            : 
     554                 :            :                 // TODO: check certificate length ???
     555         [ #  # ]:          0 :                 if ( sh.certificateLength == 0 )
     556                 :          0 :                         Weird("SSLv2: No certificate in SERVER-HELLO!");
     557                 :            : 
     558                 :            :                 // The CIPHER-SPECS-LENGTH must be > zero and a multiple of 3.
     559         [ #  # ]:          0 :                 if ( sh.cipherSpecLength == 0 )
     560                 :          0 :                         Weird("SSLv2: No CIPHER-SPECS in SERVER-HELLO!");
     561                 :            : 
     562         [ #  # ]:          0 :                 if ( sh.cipherSpecLength % 3 != 0 )
     563                 :            :                         {
     564                 :          0 :                         Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in SERVER-HELLO");
     565                 :          0 :                         return ERROR_REQUIRED;
     566                 :            :                         }
     567                 :            : 
     568                 :          0 :                 const u_char* ptr = recordData;
     569                 :          0 :                 ptr += sh.certificateLength + SSLv2_SERVER_HELLO_HEADER_SIZE;
     570                 :          0 :                 currentCipherSuites = analyzeCiphers(s, sh.cipherSpecLength, ptr);
     571                 :            : 
     572                 :          0 :                 nextState = NEW_SESSION;
     573                 :            :                 }
     574                 :            : 
     575                 :            :         // Check if at least one cipher is supported by the client.
     576 [ #  # ][ #  # ]:          0 :         if ( pClientCipherSpecs && pServerCipherSpecs )
     577                 :            :                 {
     578                 :          0 :                 bool bFound = false;
     579         [ #  # ]:          0 :                 for ( int i = 0; i < pClientCipherSpecs->len; i += 3 )
     580                 :            :                         {
     581         [ #  # ]:          0 :                         for ( int j = 0; j < pServerCipherSpecs->len; j += 3 )
     582                 :            :                                 {
     583         [ #  # ]:          0 :                                 if ( memcmp(pClientCipherSpecs + i,
     584                 :            :                                             pServerCipherSpecs + j, 3) == 0 )
     585                 :            :                                         {
     586                 :          0 :                                         bFound = true;
     587                 :          0 :                                         i = pClientCipherSpecs->len;
     588                 :          0 :                                         break;
     589                 :            :                                         }
     590                 :            :                                 }
     591                 :            :                         }
     592                 :            : 
     593         [ #  # ]:          0 :                 if ( ! bFound )
     594                 :            :                         {
     595                 :          0 :                         Weird("SSLv2: Client's and server's CIPHER-SPECS don't match!");
     596                 :          0 :                         nextState = ERROR_REQUIRED;
     597                 :            :                         }
     598                 :            : 
     599         [ #  # ]:          0 :                 delete pClientCipherSpecs;
     600                 :          0 :                 pClientCipherSpecs = 0;
     601                 :            :                 }
     602                 :            : 
     603                 :            :         // Certificate analysis.
     604 [ #  # ][ #  # ]:          0 :         if ( sh.certificateLength > 0 && ssl_analyze_certificates != 0 )
     605                 :            :                 {
     606                 :            :                 analyzeCertificate(s, recordData + SSLv2_SERVER_HELLO_HEADER_SIZE,
     607                 :          0 :                         sh.certificateLength, sh.certificateType, false);
     608                 :            :                 }
     609                 :            : 
     610         [ #  # ]:          0 :         if ( nextState == NEW_SESSION )
     611                 :            :                 // generate server-reply event
     612                 :          0 :                 fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
     613                 :            : 
     614         [ #  # ]:          0 :         else if ( nextState == CACHED_SESSION )
     615                 :            :                 { // generate server-reply event
     616                 :          0 :                 fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
     617                 :            :                 // Generate a connection-established event with a dummy
     618                 :            :                 // cipher suite, since we can't remember session information
     619                 :            :                 // (yet).
     620                 :            :                 // Note: A new session identifier is sent encrypted in SSLv2!
     621                 :          0 :                 fire_ssl_conn_established(sh.serverVersion, 0xABCD);
     622                 :            :                 }
     623                 :            :         else
     624                 :            :                 // Unref, since the table is not delivered to any event.
     625                 :          0 :                 Unref(currentCipherSuites);
     626                 :            : 
     627                 :          0 :         return nextState;
     628                 :            :         }
     629                 :            : 
     630                 :            : /*!
     631                 :            :  * This method analyses a SSLv2 CLIENT-MASTER-KEY record.
     632                 :            :  *
     633                 :            :  * \param s Pointer to the endpoint which sent the record
     634                 :            :  * \param length length of SSLv2 CLIENT-MASTER-KEY record
     635                 :            :  * \param data pointer to SSLv2 CLIENT-MASTER-KEY record to analyze
     636                 :            :  *
     637                 :            :  * \return the updated state of the current ssl connection
     638                 :            :  */
     639                 :            : SSLv2_States SSLv2_Interpreter::
     640                 :            :         ClientMasterKeyRecord(SSL_InterpreterEndpoint* s, int recordLength,
     641                 :          0 :                                 const u_char* recordData)
     642                 :            :         {
     643                 :          0 :         ++clientMasterKeyRecords;
     644                 :          0 :         SSLv2_States nextState = CLIENT_MASTERKEY_SEEN;
     645                 :            : 
     646         [ #  # ]:          0 :         if ( s != orig )
     647                 :          0 :                 Weird("SSLv2: CLIENT-MASTER-KEY from server!");
     648                 :            : 
     649         [ #  # ]:          0 :         if ( recordLength < SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE )
     650                 :            :                 {
     651                 :          0 :                 Weird("SSLv2: CLIENT-MASTER-KEY is too small!");
     652                 :          0 :                 return ERROR_REQUIRED;
     653                 :            :                 }
     654                 :            : 
     655                 :            :         // Extract the data of the client master key header.
     656                 :            :         SSLv2_ClientMasterKeyHeader cmk;
     657                 :            :         cmk.cipherKind =
     658                 :          0 :                 ((recordData[1] << 16) | recordData[2] << 8) | recordData[3];
     659                 :          0 :         cmk.clearKeyLength = uint16(recordData[4] << 8) | recordData[5];
     660                 :          0 :         cmk.encryptedKeyLength = uint16(recordData[6] << 8) | recordData[7];
     661                 :          0 :         cmk.keyArgLength = uint16(recordData[8] << 8) | recordData[9];
     662                 :            : 
     663         [ #  # ]:          0 :         if ( cmk.clearKeyLength + cmk.encryptedKeyLength + cmk.keyArgLength +
     664                 :            :              SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE != recordLength )
     665                 :            :                 {
     666                 :          0 :                 Weird("SSLv2: Size inconsistency in CLIENT-MASTER-KEY");
     667                 :          0 :                 return ERROR_REQUIRED;
     668                 :            :                 }
     669                 :            : 
     670                 :            :         // Check if cipher is supported by the server.
     671         [ #  # ]:          0 :         if ( pServerCipherSpecs )
     672                 :            :                 {
     673                 :          0 :                 bool bFound = false;
     674         [ #  # ]:          0 :                 for ( int i = 0; i < pServerCipherSpecs->len; i += 3 )
     675                 :            :                         {
     676                 :            :                         uint32 cipherSpec =
     677                 :            :                                 ((pServerCipherSpecs->data[i] << 16) |
     678                 :            :                                  pServerCipherSpecs->data[i+1] << 8) |
     679                 :          0 :                                 pServerCipherSpecs->data[i+2];
     680                 :            : 
     681         [ #  # ]:          0 :                         if ( cmk.cipherKind == cipherSpec )
     682                 :            :                                 {
     683                 :          0 :                                 bFound = true;
     684                 :          0 :                                 break;
     685                 :            :                                 }
     686                 :            :                         }
     687                 :            : 
     688         [ #  # ]:          0 :                 if ( ! bFound )
     689                 :            :                         {
     690                 :          0 :                         Weird("SSLv2: Client chooses unadvertised cipher in CLIENT-MASTER-KEY!");
     691                 :          0 :                         nextState = ERROR_REQUIRED;
     692                 :            :                         }
     693                 :            :                 else
     694                 :          0 :                         nextState = CLIENT_MASTERKEY_SEEN;
     695                 :            : 
     696         [ #  # ]:          0 :                 delete pServerCipherSpecs;
     697                 :          0 :                 pServerCipherSpecs = 0;
     698                 :            :                 }
     699                 :            : 
     700                 :            :         // TODO: check if cipher has been advertised before.
     701                 :            : 
     702                 :          0 :         SSL_CipherSpec* pCipherSpecTemp = 0;
     703                 :            : 
     704                 :          0 :         HashKey h(static_cast<bro_uint_t>(cmk.cipherKind));
     705                 :          0 :         pCipherSpecTemp = (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
     706   [ #  #  #  # ]:          0 :         if ( ! pCipherSpecTemp || ! (pCipherSpecTemp->flags & SSL_FLAG_SSLv20) )
     707                 :          0 :                 Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-MASTER-KEY!");
     708                 :            :         else
     709                 :            :                 { // check for conistency of clearKeyLength
     710         [ #  # ]:          0 :                 if ( cmk.clearKeyLength * 8 != pCipherSpecTemp->clearKeySize )
     711                 :            :                         {
     712                 :          0 :                         Weird("SSLv2: Inconsistency of clearKeyLength in CLIENT-MASTER-KEY!");
     713                 :            :                         // nextState = ERROR_REQUIRED;
     714                 :            :                         }
     715                 :            : 
     716                 :            :                 // TODO: check for consistency of encryptedKeyLength.
     717                 :            :                 // TODO: check for consistency of keyArgLength.
     718                 :            : //              switch ( cmk.cipherKind )
     719                 :            : //                      {
     720                 :            : //                      case SSL_CK_RC4_128_WITH_MD5:
     721                 :            : //                      case SSL_CK_RC4_128_EXPORT40_WITH_MD5:
     722                 :            : //                              if ( cmk.keyArgLength != 0 )
     723                 :            : //                                      {
     724                 :            : //                                      Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
     725                 :            : //                                      //nextState = ERROR_REQUIRED;
     726                 :            : //                                      }
     727                 :            : //                      break;
     728                 :            : //                      case SSL_CK_DES_64_CBC_WITH_MD5:
     729                 :            : //                      case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:
     730                 :            : //                      case SSL_CK_RC2_128_CBC_WITH_MD5:
     731                 :            : //                              case SSL_CK_IDEA_128_CBC_WITH_MD5:
     732                 :            : //                      case SSL_CK_DES_192_EDE3_CBC_WITH_MD5:
     733                 :            : //                              if ( cmk.keyArgLength != 8 )
     734                 :            : //                                      {
     735                 :            : //                                      Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!");
     736                 :            : //                                      }
     737                 :            : //                      break;
     738                 :            : //                      }
     739                 :            :                 }
     740                 :            : 
     741                 :            :         // Remember the used cipher spec.
     742                 :          0 :         usedCipherSpec = SSLv2_CipherSpec(cmk.cipherKind);
     743                 :            : 
     744                 :            :         // If decrypting, store the clear key part of the master key.
     745         [ #  # ]:          0 :         if ( ssl_store_key_material /* && cmk.clearKeyLength == 11 */ )
     746                 :            :                 {
     747                 :            :                 pMasterClearKey =
     748                 :          0 :                         new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE), cmk.clearKeyLength);
     749                 :            : 
     750                 :            :                 pMasterEncryptedKey =
     751                 :          0 :                         new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE + cmk.clearKeyLength ), cmk.encryptedKeyLength);
     752                 :            :                 }
     753                 :            : 
     754         [ #  # ]:          0 :         if ( nextState == CLIENT_MASTERKEY_SEEN )
     755                 :            :                 fire_ssl_conn_established(SSLProxy_Analyzer::SSLv20,
     756                 :          0 :                                                 cmk.cipherKind);
     757                 :            : 
     758                 :          0 :         return nextState;
     759                 :            :         }
     760                 :            : 
     761                 :            : 
     762                 :            : /*!
     763                 :            :  * This method analyses a SSLv2 ERROR record.
     764                 :            :  *
     765                 :            :  * \param s Pointer to the endpoint which sent the record
     766                 :            :  * \param length length of SSLv2 ERROR record
     767                 :            :  * \param data pointer to SSLv2 ERROR record to analyze
     768                 :            :  *
     769                 :            :  * \return the updated state of the current ssl connection
     770                 :            :  */
     771                 :            : SSLv2_States SSLv2_Interpreter::ErrorRecord(SSL_InterpreterEndpoint* s,
     772                 :          0 :                                         int recordLength, const u_char* recordData)
     773                 :            :         {
     774                 :          0 :         ++errorRecords;
     775                 :            : 
     776         [ #  # ]:          0 :         if ( unsigned(recordLength) != SSLv2_ERROR_RECORD_SIZE )
     777                 :            :                 {
     778                 :          0 :                 Weird("SSLv2: Size mismatch in Error Record!");
     779                 :          0 :                 return ERROR_REQUIRED;
     780                 :            :                 }
     781                 :            : 
     782                 :            :         SSLv2_ErrorRecord er;
     783                 :          0 :         er.errorCode = (recordData[1] << 8) | recordData[2];
     784                 :          0 :         SSL3x_AlertLevel al = SSL3x_AlertLevel(255);
     785                 :            : 
     786   [ #  #  #  #  :          0 :         switch ( er.errorCode ) {
                      # ]
     787                 :            :         case SSLv2_PE_NO_CIPHER:
     788                 :            :                 // The client doesn't support a cipher which the server
     789                 :            :                 // supports.  Only from client to server and not recoverable!
     790                 :          0 :                 al = SSL3x_ALERT_LEVEL_FATAL;
     791                 :          0 :                 break;
     792                 :            : 
     793                 :            :         case SSLv2_PE_NO_CERTIFICATE:
     794         [ #  # ]:          0 :                 if ( s == orig )
     795                 :            :                         // from client to server: not recoverable
     796                 :          0 :                         al = SSL3x_ALERT_LEVEL_FATAL;
     797                 :            :                 else
     798                 :            :                         // from server to client: recoverable
     799                 :          0 :                         al = SSL3x_ALERT_LEVEL_WARNING;
     800                 :          0 :                 break;
     801                 :            : 
     802                 :            :         case SSLv2_PE_BAD_CERTIFICATE:
     803         [ #  # ]:          0 :                 if ( s == orig )
     804                 :            :                         // from client to server: not recoverable
     805                 :          0 :                         al = SSL3x_ALERT_LEVEL_FATAL;
     806                 :            :                 else
     807                 :            :                         // from server to client: recoverable
     808                 :          0 :                         al = SSL3x_ALERT_LEVEL_WARNING;
     809                 :          0 :                 break;
     810                 :            : 
     811                 :            :         case SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
     812         [ #  # ]:          0 :                 if ( s == orig )
     813                 :            :                         // from client to server: not recoverable
     814                 :          0 :                         al = SSL3x_ALERT_LEVEL_FATAL;
     815                 :            :                 else
     816                 :            :                         // from server to client: recoverable
     817                 :          0 :                         al = SSL3x_ALERT_LEVEL_WARNING;
     818                 :          0 :                 break;
     819                 :            : 
     820                 :            :         default:
     821                 :          0 :                 al = SSL3x_ALERT_LEVEL_FATAL;
     822                 :            :                 break;
     823                 :            :         }
     824                 :            : 
     825                 :          0 :         fire_ssl_conn_alert(SSLProxy_Analyzer::SSLv20, al, er.errorCode);
     826                 :            : 
     827                 :          0 :         return ERROR_SEEN;
     828                 :            :         }
     829                 :            : 
     830                 :            : /*!
     831                 :            :  * This method analyses a set of SSLv2 cipher suites.
     832                 :            :  *
     833                 :            :  * \param s Pointer to the endpoint which sent the cipher suites
     834                 :            :  * \param length length of cipher suites
     835                 :            :  * \param data pointer to cipher suites to analyze
     836                 :            :  *
     837                 :            :  * \return a pointer to a Bro TableVal (of type cipher_suites_list) which contains
     838                 :            :  *         the cipher suites list of the current analyzed record
     839                 :            :  */
     840                 :            : TableVal* SSLv2_Interpreter::analyzeCiphers(SSL_InterpreterEndpoint* s,
     841                 :          0 :                                                 int length, const u_char* data)
     842                 :            :         {
     843         [ #  # ]:          0 :         if ( length > MAX_CIPHERSPEC_SIZE )
     844                 :            :                 {
     845         [ #  # ]:          0 :                 if ( s == orig )
     846                 :          0 :                         Weird("SSLv2: Client has CipherSpecs > MAX_CIPHERSPEC_SIZE");
     847                 :            :                 else
     848                 :          0 :                         Weird("SSLv2: Server has CipherSpecs > MAX_CIPHERSPEC_SIZE");
     849                 :            :                 }
     850                 :            :         else
     851                 :            :                 { // cipher specs are not too big
     852         [ #  # ]:          0 :                 if ( ssl_compare_cipherspecs )
     853                 :            :                         { // store cipher specs for state analysis
     854         [ #  # ]:          0 :                         if ( s == resp )
     855                 :            :                                 pServerCipherSpecs =
     856                 :          0 :                                         new SSL_DataBlock(data, length);
     857                 :            :                         else
     858                 :            :                                 pClientCipherSpecs =
     859                 :          0 :                                         new SSL_DataBlock(data, length);
     860                 :            :                         }
     861                 :            :                 }
     862                 :            : 
     863                 :          0 :         const u_char* pCipher = data;
     864                 :          0 :         bool bExtractCipherSuite = false;
     865                 :          0 :         TableVal* pCipherTable = 0;
     866                 :            : 
     867                 :            :         // We only extract the cipher suite when the corresponding
     868                 :            :         // ssl events are defined (otherwise we do work for nothing
     869                 :            :         // and suffer a memory leak).
     870                 :            :         // FIXME: This check needs to be done only once!
     871 [ #  # ][ #  # ]:          0 :         if ( (s == orig && ssl_conn_attempt) ||
         [ #  # ][ #  # ]
                 [ #  # ]
     872                 :            :              (s == resp && ssl_conn_server_reply) )
     873                 :            :                 {
     874                 :          0 :                 pCipherTable = new TableVal(cipher_suites_list);
     875                 :          0 :                 bExtractCipherSuite = true;
     876                 :            :                 }
     877                 :            : 
     878         [ #  # ]:          0 :         for ( int i = 0; i < length; i += 3 )
     879                 :            :                 {
     880                 :            :                 SSL_CipherSpec* pCurrentCipherSpec;
     881                 :            :                 uint32 cipherSpecID =
     882                 :          0 :                         ((pCipher[0] << 16) | pCipher[1] << 8) | pCipher[2];
     883                 :            : 
     884                 :            :                 // Check for unknown cipher specs.
     885                 :          0 :                 HashKey h(static_cast<bro_uint_t>(cipherSpecID));
     886                 :            :                 pCurrentCipherSpec =
     887                 :          0 :                         (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
     888                 :            : 
     889         [ #  # ]:          0 :                 if ( ! pCurrentCipherSpec )
     890                 :            :                         {
     891         [ #  # ]:          0 :                         if ( s == orig )
     892                 :          0 :                                 Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-HELLO!");
     893                 :            :                         else
     894                 :          0 :                                 Weird("SSLv2: Unknown CIPHER-SPEC in SERVER-HELLO!");
     895                 :            :                         }
     896                 :            : 
     897         [ #  # ]:          0 :                 if ( bExtractCipherSuite )
     898                 :            :                         {
     899                 :          0 :                         Val* index = new Val(cipherSpecID, TYPE_COUNT);
     900                 :          0 :                         pCipherTable->Assign(index, 0);
     901                 :          0 :                         Unref(index);
     902                 :            :                         }
     903                 :            : 
     904                 :          0 :                 pCipher += 3;
     905                 :            :                 }
     906                 :            : 
     907                 :          0 :         return pCipherTable;
     908                 :            :         }
     909                 :            : 
     910                 :            : // --- SSLv2_EndPoint ---------------------------------------------------------
     911                 :            : 
     912                 :            : /*!
     913                 :            :  * The constructor.
     914                 :            :  *
     915                 :            :  * \param interpreter Pointer to the SSLv2 interpreter to whom this endpoint belongs to
     916                 :            :  * \param is_orig true if this is the originating endpoint of the ssl connection,
     917                 :            :  *                false otherwise
     918                 :            :  */
     919                 :          0 : SSLv2_Endpoint::SSLv2_Endpoint(SSLv2_Interpreter* interpreter, int is_orig)
     920                 :          0 : : SSL_InterpreterEndpoint(interpreter, is_orig)
     921                 :            :         {
     922                 :          0 :         sentRecords = 0;
     923                 :          0 :         }
     924                 :            : 
     925                 :            : /*!
     926                 :            :  * The destructor.
     927                 :            :  */
     928                 :          0 : SSLv2_Endpoint::~SSLv2_Endpoint()
     929                 :            :         {
     930 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     931                 :            : 
     932                 :            : /*!
     933                 :            :  * This method is called by the SSLProxy_Analyzer with a complete reassembled
     934                 :            :  * SSLv2 record. It passes the record to SSLv2_Interpreter::NewSSLRecord().
     935                 :            :  *
     936                 :            :  * \param t <b>reserved</b> (always zero)
     937                 :            :  * \param seq <b>reserved</b> (always zero)
     938                 :            :  * \param len length of the data block containing the ssl record
     939                 :            :  * \param data pointer to the data block containing the ssl record
     940                 :            :  */
     941                 :          0 : void SSLv2_Endpoint::Deliver(int len, const u_char* data)
     942                 :            :         {
     943                 :          0 :         ++((SSLv2_Endpoint*)peer)->sentRecords;
     944                 :            : 
     945                 :          0 :         ((SSLv2_Interpreter*)interpreter)->NewSSLRecord(this, len, data);
     946 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8