LCOV - code coverage report
Current view: top level - src - SSLProxy.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 321 0.6 %
Date: 2010-12-13 Functions: 2 36 5.6 %
Branches: 2 199 1.0 %

           Branch data     Line data    Source code
       1                 :            : // $Id: SSLProxy.cc 6008 2008-07-23 00:24:22Z vern $
       2                 :            : 
       3                 :            : #include "SSLProxy.h"
       4                 :            : #include "SSLv3.h"
       5                 :            : #include "SSLv2.h"
       6                 :            : 
       7                 :            : // --- Initalization of static variables --------------------------------------
       8                 :            : 
       9                 :            : uint SSLProxy_Analyzer::totalPackets = 0;
      10                 :            : uint SSLProxy_Analyzer::totalRecords = 0;
      11                 :            : uint SSLProxy_Analyzer::nonSSLConnections = 0;
      12                 :            : 
      13                 :            : // --- SSL_DataBlock --------------------------------------------------------
      14                 :            : 
      15                 :            : /*!
      16                 :            :  * This constructor will allocate a block of data on the heap. If min_len is
      17                 :            :  * given, it will determine the minimum size of the new block. The data block
      18                 :            :  * referenced by data will be then be copied into the new block.
      19                 :            :  *
      20                 :            :  * \param data    Pointer to the data which will be copied into the newly
      21                 :            :  *                allocated heap block.
      22                 :            :  * \param len     Length of the data block to copy.
      23                 :            :  * \param min_len The minimum size of data to allocate on the heap, can be omitted.
      24                 :            :  */
      25                 :            : 
      26                 :          0 : SSL_DataBlock::SSL_DataBlock(const u_char* arg_data, int len, int min_len)
      27                 :            :         {
      28                 :            :         // For performance reasons, we allocate at least min_len.
      29 [ #  # ][ #  # ]:          0 :         if ( len < min_len )
      30                 :            :                 {
      31                 :          0 :                 data = new u_char[min_len];
      32                 :          0 :                 size = min_len;
      33                 :            :                 }
      34                 :            :         else
      35                 :            :                 {
      36                 :          0 :                 data = new u_char[len];
      37                 :          0 :                 this->size = len;
      38                 :            :                 }
      39                 :            : 
      40                 :          0 :         memcpy(data, arg_data, len);
      41                 :          0 :         this->len = len;
      42                 :          0 :         next = 0;
      43                 :          0 :         }
      44                 :            : 
      45                 :            : /*!
      46                 :            :  * This is an experimental function which will print the contents of the
      47                 :            :  * internal data block in a human-readable fashion to a stream.
      48                 :            :  *
      49                 :            :  * \param stream The stream for printing the data block to.
      50                 :            :  */
      51                 :            : 
      52                 :          0 : void SSL_DataBlock::toStream(FILE* stream) const
      53                 :            :         {
      54         [ #  # ]:          0 :         if ( len <= 0 )
      55                 :          0 :                 return;
      56                 :            : 
      57                 :            :         int idx;
      58         [ #  # ]:          0 :         for ( idx = 0; idx < len-1; ++idx )
      59                 :          0 :                 fprintf(stream, "%02X:", data[idx]);
      60                 :            : 
      61                 :          0 :         fprintf(stream, "%02X", data[idx]);
      62                 :            :         }
      63                 :            : 
      64                 :            : /*!
      65                 :            :  * This is an experimental function which will print the contents of the
      66                 :            :  * internal data block in a human-readable fashion to a string.
      67                 :            :  *
      68                 :            :  * \return A string which has to be freed by the caller.
      69                 :            :  */
      70                 :            : 
      71                 :          0 : char* SSL_DataBlock::toString() const
      72                 :            :         {
      73         [ #  # ]:          0 :         if ( len <= 0 )
      74                 :            :                 {
      75                 :            :                 // Currently, we return an empty string if data block is empty.
      76                 :          0 :                 char* pDummy = new char[1];
      77                 :          0 :                 pDummy[0] = '\0';
      78                 :          0 :                 return pDummy;
      79                 :            :                 }
      80                 :            : 
      81                 :          0 :         char* pString = new char[len*3];
      82                 :          0 :         char* pItx = pString;
      83                 :            : 
      84                 :            :         int idx;
      85         [ #  # ]:          0 :         for ( idx = 0; idx < len-1; ++idx )
      86                 :            :                 {
      87                 :          0 :                 sprintf(pItx, "%02X:", data[idx]);
      88                 :          0 :                 pItx += 3;
      89                 :            :                 }
      90                 :            : 
      91                 :          0 :         sprintf(pItx, "%02X", data[idx]);
      92                 :            : 
      93                 :          0 :         return pString;
      94                 :            :         }
      95                 :            : 
      96                 :            : // --- SSL_RecordBuilder ------------------------------------------------------
      97                 :            : 
      98                 :            : uint SSL_RecordBuilder::maxAllocCount = 0;
      99                 :            : uint SSL_RecordBuilder::maxFragmentCount = 0;
     100                 :            : uint SSL_RecordBuilder::fragmentedHeaders = 0;
     101                 :            : 
     102                 :            : /*!
     103                 :            :  * The constructor takes an Contents_SSL as parameter. Whenever a SSL
     104                 :            :  * record has been reassembled, the DoDeliver() function of this
     105                 :            :  * Contents_SSL will be called.
     106                 :            :  *
     107                 :            :  * \param sslEndpoint The Contents_SSL to which this instance of
     108                 :            :  *        SSL_RecordBuilder is bound.
     109                 :            :  */
     110                 :            : 
     111                 :          0 : SSL_RecordBuilder::SSL_RecordBuilder(Contents_SSL* arg_sslEndpoint)
     112                 :            :         {
     113                 :          0 :         head = tail = 0;
     114                 :          0 :         currentSize = 0;
     115                 :          0 :         expectedSize = -1; // -1 means we don't know yet
     116                 :          0 :         hasPendingData = false;
     117                 :          0 :         fragmentCounter = 0;
     118                 :          0 :         neededSize = 5;  // we need at least 5 bytes to determine version
     119                 :            : 
     120                 :          0 :         sslEndpoint = arg_sslEndpoint;
     121                 :          0 :         }
     122                 :            : 
     123                 :            : /*!
     124                 :            :  * The destructor frees the chain of SSL_DataBlocks.
     125                 :            :  */
     126                 :            : 
     127                 :          0 : SSL_RecordBuilder::~SSL_RecordBuilder()
     128                 :            :         {
     129                 :            :         // Free the data chain.
     130                 :          0 :         SSL_DataBlock* idx = head;
     131                 :            :         SSL_DataBlock* rm;
     132                 :            : 
     133 [ #  # ][ #  # ]:          0 :         while ( idx )
     134                 :            :                 {
     135                 :          0 :                 rm  = idx;
     136                 :          0 :                 idx = idx->next;
     137 [ #  # ][ #  # ]:          0 :                 delete rm;
     138                 :            :                 }
     139                 :          0 :         }
     140                 :            : 
     141                 :            : /*!
     142                 :            :  * This function is the main entry point of the class. Call it with a segment
     143                 :            :  * of data to process.
     144                 :            :  *
     145                 :            :  * \param data   pointer to a data segment that will be reassembled
     146                 :            :  * \param length length of the data segment to be reassembled
     147                 :            :  *
     148                 :            :  * \return true if succesfull, false otherwise
     149                 :            :  */
     150                 :            : 
     151                 :          0 : bool SSL_RecordBuilder::addSegment(const u_char* data, int length)
     152                 :            :         {
     153         [ #  # ]:          0 :         while ( length > 0 )
     154                 :            :                 {
     155         [ #  # ]:          0 :                 if ( ! head )
     156                 :            :                         {
     157                 :            :                         // This is the first fragment of a SSLv2 record,
     158                 :            :                         // so we analyze the header.
     159                 :            : 
     160                 :            :                         // Special case: SSL header has been fragmented.
     161         [ #  # ]:          0 :                         if ( length < neededSize )
     162                 :            :                                 {
     163                 :            :                                 // We can't determine the record size yet,
     164                 :            :                                 // so we just add this stuff.
     165                 :          0 :                                 ++fragmentedHeaders;
     166                 :            :                                 head = tail = new SSL_DataBlock(data, length,
     167                 :          0 :                                                                 MIN_ALLOC_SIZE);
     168                 :          0 :                                 currentSize += length;
     169                 :          0 :                                 expectedSize = -1;      // special meaning
     170                 :          0 :                                 break;
     171                 :            :                                 }
     172                 :            : 
     173                 :            :                         // Get the expected length of this record.
     174         [ #  # ]:          0 :                         if ( ! computeExpectedSize(data, length) )
     175                 :          0 :                                 return false;
     176                 :            : 
     177                 :            :                         // Insert weird here replacing assert.
     178         [ #  # ]:          0 :                         if ( neededSize > expectedSize )
     179                 :            :                                 {
     180                 :          0 :                                 sslEndpoint->Weird("SSL_RecordBuilder::addSegment neededSize > expectedSize");
     181                 :          0 :                                 return false;
     182                 :            :                                 }
     183                 :            : 
     184         [ #  # ]:          0 :                         if ( tail != 0 )
     185                 :            :                                 {
     186                 :          0 :                                 sslEndpoint->Parent()->Weird("SSL_RecordBuilder::addSegment tail != 0");
     187                 :          0 :                                 return false;
     188                 :            :                                 }
     189                 :            : 
     190         [ #  # ]:          0 :                         if ( length > expectedSize )
     191                 :            :                                 {
     192                 :            :                                 // No fragmentation -> no memory-reallocation.
     193                 :            :                                 // We have additional data pending.
     194                 :          0 :                                 hasPendingData = true;
     195                 :          0 :                                 sslEndpoint->DoDeliver(expectedSize, data);
     196                 :          0 :                                 length -= expectedSize;
     197                 :          0 :                                 data += expectedSize;
     198                 :          0 :                                 expectedSize = -1;
     199                 :            :                                 }
     200                 :            : 
     201         [ #  # ]:          0 :                         else if ( length == expectedSize )
     202                 :            :                                 {
     203                 :            :                                 // No fragmentation -> no memory-reallocation.
     204                 :            :                                 // No additional data pending.
     205                 :          0 :                                 hasPendingData = false;
     206                 :          0 :                                 sslEndpoint->DoDeliver(expectedSize, data);
     207                 :          0 :                                 length -= expectedSize;
     208                 :          0 :                                 data += expectedSize;
     209                 :          0 :                                 expectedSize = -1;
     210                 :          0 :                                 break;
     211                 :            :                                 }
     212                 :            :                         else
     213                 :            : 
     214                 :            :                                 {
     215                 :            :                                 // First fragment of a record.
     216                 :            :                                 head = tail = new SSL_DataBlock(data, length,
     217                 :          0 :                                                                 MIN_ALLOC_SIZE);
     218                 :          0 :                                 currentSize += length;
     219                 :          0 :                                 break;
     220                 :            :                                 }
     221                 :            : 
     222                 :          0 :                         continue;
     223                 :            :                         }
     224                 :            : 
     225                 :            :                 // ! head.
     226                 :            :                 // We already have some data, so add the current
     227                 :            :                 // segment special case.
     228         [ #  # ]:          0 :                 if ( expectedSize < 0 )
     229                 :            :                         {
     230                 :            :                         // We don't know the expected size of
     231                 :            :                         // this record yet.
     232         [ #  # ]:          0 :                         if ( currentSize + length < neededSize )
     233                 :            :                                 {
     234                 :            :                                 // We still can't determine the expected size,
     235                 :            :                                 // so we just add the current fragment.
     236                 :          0 :                                 addData(data, length);
     237                 :          0 :                                 break;
     238                 :            :                                 }
     239                 :            : 
     240                 :            :                         // Now we can determine the expected size the
     241                 :            :                         // header has been fragmented, so we have to
     242                 :            :                         // reassemble it.
     243                 :          0 :                         uint8 Header[neededSize];
     244                 :          0 :                         memcpy(Header, head->data, head->len);
     245                 :          0 :                         memcpy(Header + head->len, data, neededSize - head->len);
     246         [ #  # ]:          0 :                         if ( ! computeExpectedSize(Header, neededSize) )
     247                 :            :                                 {
     248                 :            :                                 // Since neededSize <= MIN_ALLOC_SIZE,
     249                 :            :                                 // we free only head.
     250         [ #  # ]:          0 :                                 delete head;
     251                 :          0 :                                 head = tail = 0;
     252                 :          0 :                                 return false;
     253                 :            :                                 }
     254                 :            : 
     255         [ #  # ]:          0 :                         if ( neededSize > expectedSize )
     256                 :            :                                 {
     257                 :          0 :                                 sslEndpoint->Parent()->Weird("SSL_RecordBuilder::addSegment neededSize > expectedSize");
     258      [ #  #  # ]:          0 :                                 return false;
     259                 :            :                                 }
     260                 :            : 
     261                 :            :                         // No break, go on with this packet.
     262                 :            :                         }
     263                 :            : 
     264         [ #  # ]:          0 :                 if ( currentSize + length == expectedSize )
     265                 :            :                         { // this is exactly the last segment of the record
     266                 :          0 :                         hasPendingData = false;
     267                 :            : 
     268                 :            :                         // Create a continuous data structure and call
     269                 :            :                         // DoDeliver().
     270                 :          0 :                         u_char* pBlock = assembleBlocks(data, length);
     271                 :          0 :                         sslEndpoint->DoDeliver(expectedSize, pBlock);
     272         [ #  # ]:          0 :                         delete [] pBlock;
     273                 :          0 :                         expectedSize = -1;
     274                 :          0 :                         break;
     275                 :            :                         }
     276                 :            : 
     277         [ #  # ]:          0 :                 else if ( currentSize + length < expectedSize )
     278                 :            :                         { // another (middle) segment
     279         [ #  # ]:          0 :                         if ( length <= MIN_FRAGMENT_SIZE )
     280                 :          0 :                                 sslEndpoint->Parent()->Weird( "SSLProxy: Excessive small TCP Segment!" );
     281                 :            : 
     282                 :          0 :                         addData(data, length);
     283                 :          0 :                         break;
     284                 :            :                         }
     285                 :            : 
     286                 :            :                 else
     287                 :            :                         {
     288                 :            :                         // This is the last fragment of the current record,
     289                 :            :                         // but there's more data in this segment.
     290                 :          0 :                         int deltaSize = expectedSize - currentSize;
     291                 :          0 :                         hasPendingData = true;
     292                 :            : 
     293                 :            :                         // Create a continuous data structure and call
     294                 :            :                         // DoDeliver().
     295                 :          0 :                         u_char* pBlock = assembleBlocks(data, deltaSize);
     296                 :          0 :                         sslEndpoint->DoDeliver(expectedSize, pBlock);
     297         [ #  # ]:          0 :                         delete [] pBlock;
     298                 :          0 :                         expectedSize = -1;
     299                 :            : 
     300                 :            :                         // Process the rest.
     301                 :          0 :                         length -= deltaSize;
     302                 :          0 :                         data += deltaSize;
     303                 :            :                         }
     304                 :            :                 } // while
     305                 :            : 
     306                 :          0 :         return true;
     307                 :            :         }
     308                 :            : 
     309                 :            : /*!
     310                 :            :  * This function is called internally by addSegment(), and add's a new SSL
     311                 :            :  * record fragment to the internally used list of SSL_DataBlocks. Note that
     312                 :            :  * the data will be copied!
     313                 :            :  *
     314                 :            :  * \param data   pointer to the data that will be added
     315                 :            :  * \param length length of the data that will be added
     316                 :            :  */
     317                 :            : 
     318                 :          0 : inline void SSL_RecordBuilder::addData(const u_char* data, int length)
     319                 :            :         {
     320                 :          0 :         ++fragmentCounter;
     321                 :            : 
     322                 :            :         // Check if there's some space left in the last datablock.
     323                 :          0 :         int bytesLeft = tail->size - tail->len;
     324         [ #  # ]:          0 :         if ( bytesLeft > 0 )
     325                 :            :                 {
     326                 :            :                 // There's some space left in the last data block.
     327         [ #  # ]:          0 :                 if ( bytesLeft >= length )
     328                 :            :                         {
     329                 :            :                         // We can store all bytes in the last data block.
     330                 :          0 :                         memcpy(tail->data + tail->len, data, length);
     331                 :          0 :                         tail->len += length;
     332                 :          0 :                         currentSize += length;
     333                 :            :                         }
     334                 :            :                 else
     335                 :            :                         {
     336                 :            :                         // We cannot store all bytes in the last data block,
     337                 :            :                         // so we also need to add a new one.
     338                 :          0 :                         memcpy(tail->data + tail->len, data, bytesLeft);
     339                 :          0 :                         tail->len = tail->size;
     340                 :          0 :                         currentSize += length;
     341                 :            : 
     342                 :          0 :                         data += bytesLeft;
     343                 :          0 :                         length -= bytesLeft;
     344                 :            : 
     345                 :          0 :                         tail->next = new SSL_DataBlock(data, length, MIN_ALLOC_SIZE);
     346                 :          0 :                         tail = tail->next;
     347                 :            :                         }
     348                 :            :                 }
     349                 :            : 
     350                 :            :         else
     351                 :            :                 {
     352                 :            :                 // Last data block is full.
     353                 :          0 :                 tail->next = new SSL_DataBlock(data, length, MIN_ALLOC_SIZE);
     354                 :          0 :                 tail = tail->next;
     355                 :          0 :                 currentSize += length;
     356                 :            :                 }
     357                 :          0 :         }
     358                 :            : 
     359                 :            : /*!
     360                 :            :  * This function is called internally by addSegment(), whenever a SSL record
     361                 :            :  * has been fully received. It creates a single data block from the list of
     362                 :            :  * SSL record fragments while freeing them.
     363                 :            :  *
     364                 :            :  * \param data   pointer to the last SSL record fragment
     365                 :            :  * \param length size of the last SSL record fragment
     366                 :            :  *
     367                 :            :  * \return pointer to a data block which contains the reassembled SSL record
     368                 :            :  */
     369                 :            : 
     370                 :          0 : u_char* SSL_RecordBuilder::assembleBlocks(const u_char* data, int length)
     371                 :            :         {
     372                 :            :         // We don't store the last SSL record fragment in a DataBlock,
     373                 :            :         // instead we get it directly as parameter.
     374                 :          0 :         u_char* dataptr = new u_char[currentSize + length];
     375                 :          0 :         u_char* nextseg = dataptr;
     376                 :            : 
     377                 :          0 :         SSL_DataBlock* idx = head;
     378                 :            :         SSL_DataBlock* rm;
     379                 :          0 :         uint allocCounter = 0;
     380                 :            : 
     381         [ #  # ]:          0 :         while ( idx )
     382                 :            :                 {
     383                 :          0 :                 ++allocCounter;
     384                 :          0 :                 memcpy(nextseg, idx->data, idx->len);
     385                 :          0 :                 nextseg += idx->len;
     386                 :          0 :                 rm = idx;
     387                 :          0 :                 idx = idx->next;
     388         [ #  # ]:          0 :                 delete rm;
     389                 :            :                 }
     390                 :            : 
     391                 :            :         // The last fragment isn't stored in a datablock.
     392                 :          0 :         memcpy(nextseg, data, length);
     393                 :            : 
     394                 :            :         // The first and last fragments aren't counted.
     395                 :          0 :         fragmentCounter += 2;
     396                 :            : 
     397                 :            :         // Update statistics.
     398         [ #  # ]:          0 :         if ( allocCounter > maxAllocCount )
     399                 :          0 :                 maxAllocCount = allocCounter;
     400                 :            : 
     401         [ #  # ]:          0 :         if ( fragmentCounter > maxFragmentCount )
     402                 :          0 :                 maxFragmentCount = fragmentCounter;
     403                 :            : 
     404                 :          0 :         fragmentCounter = 0;
     405                 :          0 :         currentSize = 0;
     406                 :          0 :         head = tail = 0;
     407                 :            : 
     408                 :          0 :         return dataptr;
     409                 :            :         }
     410                 :            : 
     411                 :            : /*!
     412                 :            :  * This method is called internally by computeExpectedSize(), when the SSL
     413                 :            :  * record format has not been determined yet. It tries to do so by using
     414                 :            :  * heuristics, since there's no definitive way to distinguish SSLv2 vs. SSLv3
     415                 :            :  * record headers.
     416                 :            :  *
     417                 :            :  * \param data   pointer to a data block containing the SSL record to analyze
     418                 :            :  * \param length length of the SSL record to analyze, has to be >= neededSize!
     419                 :            :  *
     420                 :            :  * \return
     421                 :            :  *         -  2 for SSLv2 record format
     422                 :            :  *         -  3 for SSLv3 record format
     423                 :            :  *         - -1 if an error occurred
     424                 :            :  */
     425                 :            : 
     426                 :          0 : int SSL_RecordBuilder::analyzeSSLRecordFormat(const u_char* data, int length)
     427                 :            :         {
     428                 :            :         // We have to use heuristics for this one.
     429                 :            : 
     430         [ #  # ]:          0 :         if ( length < neededSize )
     431                 :            :                 {
     432                 :          0 :                 sslEndpoint->Parent()->Weird("SSLProxy: analyzeSSLRecordFormat length < neededSize");
     433                 :          0 :                 return -1;
     434                 :            :                 }
     435                 :            : 
     436                 :          0 :         bool found_ssl3x = 0;
     437                 :          0 :         bool found_ssl2x = 0;
     438                 :            : 
     439                 :            :         // SSLv3x-check.
     440                 :          0 :         SSL3_1_ContentType ct = SSL3_1_ContentType(uint8(*data));
     441         [ #  # ]:          0 :         switch ( ct ) {
     442                 :            :         case SSL3_1_TYPE_CHANGE_CIPHER_SPEC:
     443                 :            :         case SSL3_1_TYPE_ALERT:
     444                 :            :         case SSL3_1_TYPE_HANDSHAKE:
     445                 :            :         case SSL3_1_TYPE_APPLICATION_DATA:
     446                 :            :                 {
     447                 :          0 :                 sslEndpoint->sslVersion = ((data[1]) << 8) | data[2];
     448                 :          0 :                 uint16 v = sslEndpoint->sslVersion;
     449 [ #  # ][ #  # ]:          0 :                 if ( v == uint16(SSLProxy_Analyzer::SSLv30) ||
     450                 :            :                      v == uint16(SSLProxy_Analyzer::SSLv31) )
     451                 :          0 :                         found_ssl3x = true;
     452                 :            :                 break;
     453                 :            :                 }
     454                 :            :         }
     455                 :            : 
     456                 :            :         // SSLv2 check.
     457                 :            :         // We look for CLIENT-HELLOs, SERVER-HELLOs and ERRORs.
     458                 :          0 :         const u_char* pContents = data;
     459                 :          0 :         uint offset = 0;
     460                 :          0 :         uint16 size = 0;
     461         [ #  # ]:          0 :         if ( (data[0] & 0x80) > 0 )
     462                 :            :                 { // we have a two-byte record header
     463                 :          0 :                 offset = 2;
     464                 :          0 :                 size = (((data[0] & 0x7f) << 8) | data[1]) + 2;
     465                 :            :                 }
     466                 :            :         else
     467                 :            :                 { // we have a three-byte record header
     468                 :          0 :                 offset = 3;
     469                 :          0 :                 size = (((data[0] & 0x3f) << 8) | data[1]) + 3;
     470                 :            :                 }
     471                 :          0 :         pContents += offset;
     472                 :            : 
     473   [ #  #  #  # ]:          0 :         switch ( SSLv2_MessageTypes(pContents[0]) ) {
     474                 :            :         case SSLv2_MT_ERROR:
     475         [ #  # ]:          0 :                 if ( size == SSLv2_ERROR_RECORD_SIZE + offset)
     476                 :            :                         {
     477                 :          0 :                         found_ssl2x = true;
     478                 :            :                         sslEndpoint->sslVersion =
     479                 :          0 :                                 uint16(SSLProxy_Analyzer::SSLv20);
     480                 :            :                         }
     481                 :          0 :                 break;
     482                 :            : 
     483                 :            :         case SSLv2_MT_CLIENT_HELLO:
     484                 :            :                 {
     485                 :            :                 sslEndpoint->sslVersion =
     486                 :          0 :                         uint16(pContents[1] << 8) | pContents[2];
     487                 :          0 :                 uint16 v = sslEndpoint->sslVersion;
     488                 :            : 
     489 [ #  # ][ #  # ]:          0 :                 if ( v == SSLProxy_Analyzer::SSLv20 ||
                 [ #  # ]
     490                 :            :                      v == SSLProxy_Analyzer::SSLv30 ||
     491                 :            :                      v == SSLProxy_Analyzer::SSLv31 )
     492                 :          0 :                         found_ssl2x = true;
     493                 :          0 :                 break;
     494                 :            :                 }
     495                 :            : 
     496                 :            :         case SSLv2_MT_SERVER_HELLO:
     497                 :            :                 {
     498                 :            :                 sslEndpoint->sslVersion =
     499                 :          0 :                         uint16(pContents[3] << 8) | pContents[4];
     500                 :          0 :                 uint16 v = sslEndpoint->sslVersion;
     501                 :            : 
     502 [ #  # ][ #  # ]:          0 :                 if ( v == SSLProxy_Analyzer::SSLv20 ||
                 [ #  # ]
     503                 :            :                      v == SSLProxy_Analyzer::SSLv30 ||
     504                 :            :                      v == SSLProxy_Analyzer::SSLv31 )
     505                 :          0 :                         found_ssl2x = true;
     506                 :            :                 break;
     507                 :            :                 }
     508                 :            : 
     509                 :            :         default:
     510                 :            :                 break;
     511                 :            :         }
     512                 :            : 
     513                 :            :         // Consistency checks.
     514 [ #  # ][ #  # ]:          0 :         if ( (found_ssl3x || found_ssl2x) == false )
     515                 :            :                 {
     516                 :          0 :                 sslEndpoint->Parent()->Weird("SSLProxy: Could not determine SSL version!");
     517                 :          0 :                 return -1;
     518                 :            :                 }
     519                 :            : 
     520 [ #  # ][ #  # ]:          0 :         if ( (found_ssl3x && found_ssl2x) == true )
     521                 :            :                 {
     522                 :          0 :                 sslEndpoint->Parent()->Weird("SSLProxy: Found ambigous SSL version!");
     523                 :          0 :                 return -1;
     524                 :            :                 }
     525                 :            : 
     526         [ #  # ]:          0 :         if ( found_ssl2x )
     527                 :          0 :                 return 2;
     528                 :            :         else
     529                 :          0 :                 return 3;
     530                 :            :         }
     531                 :            : 
     532                 :            : /*!
     533                 :            :  * This method is called internally by addSegment() to determine the expected
     534                 :            :  * size of a SSL record.
     535                 :            :  *
     536                 :            :  * \param data   pointer to the SSL record to analyze
     537                 :            :  * \param length length of the SSL record to analyze
     538                 :            :  *
     539                 :            :  * \return true if succesfull, false otherwise
     540                 :            :  */
     541                 :            : 
     542                 :          0 : bool SSL_RecordBuilder::computeExpectedSize(const u_char* data, int length)
     543                 :            :         {
     544         [ #  # ]:          0 :         if ( sslEndpoint->sslRecordVersion < 0 )
     545                 :            :                 {
     546                 :            :                 // We don't know the ssl record format yet, so we try
     547                 :            :                 // to find out.
     548                 :            :                 sslEndpoint->sslRecordVersion =
     549                 :          0 :                         analyzeSSLRecordFormat(data, length);
     550                 :            : 
     551   [ #  #  #  # ]:          0 :                 if ( sslEndpoint->sslRecordVersion != 2 &&
     552                 :            :                      sslEndpoint->sslRecordVersion != 3 )
     553                 :            :                         // We could not determine the ssl record version.
     554                 :          0 :                         return false;
     555                 :            :                 }
     556                 :            : 
     557                 :            :         // Get the expected length of this record.
     558         [ #  # ]:          0 :         if ( sslEndpoint->sslRecordVersion == 2 )
     559                 :            :                 {
     560         [ #  # ]:          0 :                 if ( (data[0] & 0x80) > 0 )
     561                 :            :                         // We have a two-byte record header.
     562                 :          0 :                         expectedSize = (((data[0] & 0x7f) << 8) | data[1]) + 2;
     563                 :            :                 else
     564                 :            :                         // We have a three-byte record header.
     565                 :          0 :                         expectedSize = (((data[0] & 0x3f) << 8) | data[1]) + 3;
     566                 :            :                 }
     567                 :            : 
     568         [ #  # ]:          0 :         else if ( sslEndpoint->sslRecordVersion == 3 )
     569                 :          0 :                 expectedSize = ((data[3] << 8) | data[4]) + 5;
     570                 :            : 
     571         [ #  # ]:          0 :         if ( expectedSize < neededSize )
     572                 :            :                 {
     573                 :            :                 // This should never happen (otherwise: UNTESTED).
     574                 :          0 :                 sslEndpoint->Parent()->Weird( "SSLProxy: expectedSize < neededSize in RecordBuilder!" );
     575                 :          0 :                 return false;
     576                 :            :                 }
     577                 :            : 
     578                 :          0 :         return true;
     579                 :            :         }
     580                 :            : 
     581                 :            : 
     582                 :            : // --- SSL_Connection_Proxy ---------------------------------------------------
     583                 :            : 
     584                 :            : bool SSLProxy_Analyzer::bInited = false;
     585                 :            : 
     586                 :          0 : SSLProxy_Analyzer::SSLProxy_Analyzer(Connection* conn)
     587                 :          0 : : TCP_ApplicationAnalyzer(AnalyzerTag::SSL, conn)
     588                 :            :         {
     589                 :          0 :         sSLv2Interpreter = new SSLv2_Interpreter(this);
     590                 :          0 :         sSLv3xInterpreter = new SSLv3_Interpreter(this);
     591                 :          0 :         sSLInterpreter = 0;
     592                 :          0 :         bPassThrough = false;
     593   [ #  #  #  # ]:          0 :         if ( ! bInited )
     594                 :            :                 {
     595                 :          0 :                 BuildCipherDict();
     596                 :          0 :                 bInited = true;
     597                 :            :                 }
     598                 :            : 
     599                 :          0 :         AddSupportAnalyzer(sslpeo = new Contents_SSL(conn, true));
     600                 :          0 :         AddSupportAnalyzer(sslper = new Contents_SSL(conn, false));
     601                 :          0 :         }
     602                 :            : 
     603                 :          0 : SSLProxy_Analyzer::~SSLProxy_Analyzer()
     604                 :            :         {
     605 [ #  # ][ #  # ]:          0 :         delete sSLv2Interpreter;
                 [ #  # ]
     606 [ #  # ][ #  # ]:          0 :         delete sSLv3xInterpreter;
                 [ #  # ]
     607 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     608                 :            : 
     609                 :          0 : void SSLProxy_Analyzer::Init()
     610                 :            :         {
     611                 :          0 :         TCP_ApplicationAnalyzer::Init();
     612                 :            : 
     613                 :          0 :         sSLv2Interpreter->Init();
     614                 :          0 :         sSLv3xInterpreter->Init();
     615                 :            : 
     616                 :            :         sSLv2Interpreter->Orig()
     617                 :          0 :                 ->SetProxyEndpoint(sSLv3xInterpreter->Orig()->GetProxyEndpoint());
     618                 :            :         sSLv2Interpreter->Resp()
     619                 :          0 :                 ->SetProxyEndpoint(sSLv3xInterpreter->Resp()->GetProxyEndpoint());
     620                 :          0 :         }
     621                 :            : 
     622                 :          0 : void SSLProxy_Analyzer::BuildCipherDict()
     623                 :            :         {
     624         [ #  # ]:          0 :         for ( uint idx = 0; idx < SSL_CipherSpecs_Count; ++idx )
     625                 :            :                 {
     626                 :          0 :                 HashKey h(static_cast<bro_uint_t>(SSL_CipherSpecs[idx].identifier));
     627                 :          0 :                 SSL_CipherSpecDict.Insert(&h, &SSL_CipherSpecs[idx]);
     628                 :            :                 }
     629                 :          0 :         }
     630                 :            : 
     631                 :            : void SSLProxy_Analyzer::NewSSLRecord(Contents_SSL* endp,
     632                 :          0 :                                         int len, const u_char* data)
     633                 :            :         {
     634                 :            :         // This is to extract only SSLv2 traffic.
     635                 :            :         if ( recordSSLv2Traffic )
     636                 :            :                 {
     637                 :            :                 uint16 sslVersion = 0;
     638                 :            :                 if ( (data[0] & 0x80) > 0 )
     639                 :            :                         // We have a two-byte record header.
     640                 :            :                         sslVersion = (data[3] << 8) | data[4];
     641                 :            :                 else
     642                 :            :                         // We have a three-byte record header.
     643                 :            :                         sslVersion = (data[4] << 8) | data[5];
     644                 :            : 
     645                 :            :                 if ( ! endp->IsSSLv2Record() ||
     646                 :            :                      sslVersion != SSLProxy_Analyzer::SSLv20 )
     647                 :            :                         {
     648                 :            :                         SetSkip(1);
     649                 :            :                         Conn()->SetRecordPackets(0);
     650                 :            :                         Conn()->SetRecordContents(0);
     651                 :            :                         // FIXME: Could do memory cleanup here.
     652                 :            :                         }
     653                 :            :                 else
     654                 :            :                         // No analysis - only recording.
     655                 :            :                         SetSkip(1);
     656                 :            : 
     657                 :            :                 return;
     658                 :            :                 }
     659                 :            : 
     660         [ #  # ]:          0 :         if ( bPassThrough )
     661                 :            :                 {
     662                 :          0 :                 DoDeliver(len, data, endp->IsOrig());
     663                 :          0 :                 return;
     664                 :            :                 }
     665                 :            : 
     666         [ #  # ]:          0 :         if ( ! endp->IsSSLv2Record() )
     667                 :            :                 {
     668                 :            :                 // It's TLS or SSLv3, so we are done ...
     669                 :          0 :                 sSLInterpreter = sSLv3xInterpreter;
     670                 :          0 :                 bPassThrough = true;
     671                 :            :                 // Tell the other record builder we have SSLv3x.
     672                 :          0 :                 endp->sslRecordVersion = 3;
     673                 :          0 :                 DoDeliver(len, data, endp->IsOrig());
     674                 :            :                 }
     675                 :            : 
     676                 :            :         else
     677                 :            :                 { // we have a SSLv2 record ...
     678                 :          0 :                 sSLInterpreter = sSLv2Interpreter;
     679                 :            : 
     680                 :            :                 // Check whether it's the first or second we've seen ...
     681 [ #  # ][ #  # ]:          0 :                 if ( sslpeo->VersionRecognized() &&
                 [ #  # ]
     682                 :            :                      sslper->VersionRecognized() )
     683                 :            :                         {
     684                 :            :                         // Second record we've seen.
     685                 :            :                         // O.K. Both endpoints recognized the version.
     686                 :            :                         // So this needs to be an SSLv2-Connection ...
     687                 :          0 :                         bPassThrough = true;
     688                 :          0 :                         DoDeliver(len, data, endp->IsOrig());
     689                 :            :                         }
     690                 :            : 
     691                 :            :                 // First record we see.
     692                 :            :                 // The next one may be SSLv2 or SSLv3x,
     693                 :            :                 // we don't know yet ...
     694         [ #  # ]:          0 :                 else if ( endp->sslVersion == SSLv20 )
     695                 :            :                         {
     696                 :            :                         // The client supports only SSLv2, so we're done.
     697                 :          0 :                         bPassThrough = true;
     698                 :          0 :                         endp->sslRecordVersion = 2;
     699                 :          0 :                         endp->sslVersion = SSLv20;
     700                 :          0 :                         DoDeliver(len, data, endp->IsOrig());
     701                 :            :                         }
     702                 :            : 
     703                 :            :                 else
     704                 :            :                         {
     705                 :          0 :                         bPassThrough = false;
     706                 :          0 :                         DoDeliver(len, data, endp->IsOrig());
     707                 :            : 
     708                 :            :                         // Transfer the state of the SSLv2-Interpreter
     709                 :            :                         // to the state of the SSLv3x-Interpreter ...
     710         [ #  # ]:          0 :                         if ( ((SSLv2_Interpreter*) sSLInterpreter)->ConnState() == CLIENT_HELLO_SEEN )
     711                 :          0 :                                 ((SSLv3_Interpreter*) sSLv3xInterpreter)->SetState(SSL3_1_STATE_CLIENT_HELLO_SENT);
     712                 :            :                         }
     713                 :            :                 }
     714                 :            :         }
     715                 :            : 
     716                 :          0 : void SSLProxy_Analyzer::DoDeliver(int len, const u_char* data, bool orig)
     717                 :            :         {
     718         [ #  # ]:          0 :         if ( orig )
     719                 :          0 :                 sSLInterpreter->Orig()->Deliver(len, data);
     720                 :            :         else
     721                 :          0 :                 sSLInterpreter->Resp()->Deliver(len, data);
     722                 :          0 :         }
     723                 :            : 
     724                 :          0 : void SSLProxy_Analyzer::printStats()
     725                 :            :         {
     726                 :          0 :         printf("SSLProxy_Analyzer::totalPackets = %u\n", totalPackets);
     727                 :          0 :         printf("SSLProxy_Analyzer::totalRecords = %u\n", totalRecords);
     728                 :          0 :         printf("SSLProxy_Analyzer::nonSSLConnections = %u\n", nonSSLConnections);
     729                 :          0 :         }
     730                 :            : 
     731                 :            : 
     732                 :          0 : void SSLProxy_Analyzer::Weak(const char* name)
     733                 :            :         {
     734         [ #  # ]:          0 :         if ( ssl_conn_weak )
     735                 :          0 :                 Event(ssl_conn_weak, name);
     736                 :          0 :         }
     737                 :            : 
     738                 :            : // --- Contents_SSL ------------------------------------------------------
     739                 :            : 
     740                 :            : /*!
     741                 :            :  * mod Contents_SSL::Contents_SSL( TCP_Endpoint* arg_endpt, int stop_on_gap )
     742                 :            :  *      : TCP_Contents( arg_conn, stop_on_gap, punt_on_partial )
     743                 :            :  */
     744                 :            : 
     745                 :          0 : Contents_SSL::Contents_SSL(Connection* conn, bool orig)
     746                 :          0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_SSL, conn, orig)
     747                 :            :         {
     748                 :          0 :         sslRecordBuilder = new SSL_RecordBuilder(this);
     749                 :          0 :         bVersionRecognized = false;
     750                 :          0 :         bIsSSLv2Record = false;
     751                 :            : 
     752                 :          0 :         sslRecordVersion = -1;  // -1 means we don't know yet
     753                 :          0 :         sslVersion =  0;        // 0 means we don't know yet
     754                 :          0 :         }
     755                 :            : 
     756                 :          0 : Contents_SSL::~Contents_SSL()
     757                 :            :         {
     758 [ #  # ][ #  # ]:          0 :         delete sslRecordBuilder;
                 [ #  # ]
     759 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     760                 :            : 
     761                 :          0 : bool Contents_SSL::isDataPending()
     762                 :            :         {
     763                 :          0 :         return sslRecordBuilder->isDataPending();
     764                 :            :         }
     765                 :            : 
     766                 :          0 : void Contents_SSL::DeliverStream(int len, const u_char* data, bool orig)
     767                 :            :         {
     768                 :          0 :         TCP_SupportAnalyzer::DeliverStream(len, data, orig);
     769                 :            : 
     770                 :          0 :         TCP_Analyzer* tcp = static_cast<TCP_ApplicationAnalyzer *>(Parent())->TCP();
     771         [ #  # ]:          0 :         assert(tcp);
     772                 :            : 
     773 [ #  # ][ #  # ]:          0 :         if ( tcp->HadGap(orig) || tcp->IsPartial() )
                 [ #  # ]
     774                 :          0 :                  return;
     775                 :            : 
     776                 :          0 :         ++SSLProxy_Analyzer::totalPackets;
     777                 :            : 
     778         [ #  # ]:          0 :         TCP_Endpoint* endp = orig ? tcp->Orig() : tcp->Resp();
     779                 :            : 
     780                 :            : #if 0
     781                 :            :         // FIXME: What's this???
     782                 :            :         int ack = endp->AckSeq() - endp->StartSeq();
     783                 :            :         int top_seq = seq + len;
     784                 :            : 
     785                 :            :         if ( top_seq <= ack )
     786                 :            :                 // There is no new data in this packet.
     787                 :            :                 return;
     788                 :            : #endif
     789                 :            : 
     790         [ #  # ]:          0 :         if ( len <= 0 )
     791                 :          0 :                 return;
     792                 :            : 
     793                 :            :         // No further processing if we have a partial connection.
     794 [ #  # ][ #  # ]:          0 :         if ( endp->state == TCP_ENDPOINT_PARTIAL ||
     795                 :            :              endp->peer->state == TCP_ENDPOINT_PARTIAL )
     796                 :            :                 {
     797                 :          0 :                 Parent()->SetSkip(1);
     798                 :          0 :                 Conn()->SetRecordPackets(0);
     799                 :          0 :                 return;
     800                 :            :                 }
     801                 :            : 
     802         [ #  # ]:          0 :         if ( ! sslRecordBuilder->addSegment(data, len) )
     803                 :            :                 {
     804                 :            :                 // The RecordBuilder failed to determine the SSL record version,
     805                 :            :                 // so we can't analyze this connection any further.
     806                 :          0 :                 ++SSLProxy_Analyzer::nonSSLConnections;
     807                 :          0 :                 Parent()->Weird("SSL: Skipping connection (not an SSL connection?!)!");
     808                 :          0 :                 Parent()->SetSkip(1);
     809                 :          0 :             Conn()->SetRecordPackets(0);
     810                 :            :                 }
     811                 :            :         }
     812                 :            : 
     813                 :            : // Called by the RecordBuilder with a complete SSL record.
     814                 :          0 : void Contents_SSL::DoDeliver(int len, const u_char* data)
     815                 :            :         {
     816                 :          0 :         ++SSLProxy_Analyzer::totalRecords;
     817                 :            : 
     818                 :          0 :         bIsSSLv2Record = sslRecordVersion == 2;
     819                 :          0 :         bVersionRecognized = true;
     820                 :            : 
     821                 :          0 :         ((SSLProxy_Analyzer*) Parent())->NewSSLRecord(this, len, data);
     822                 :          0 :         }
     823                 :            : 
     824                 :          0 : bool Contents_SSL::IsSSLv2Record()
     825                 :            :         {
     826                 :          0 :         return bIsSSLv2Record;
     827                 :            :         }
     828                 :            : 
     829                 :          0 : bool Contents_SSL::VersionRecognized()
     830                 :            :         {
     831                 :          0 :         return bVersionRecognized;
     832 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8