LCOV - code coverage report
Current view: top level - src - SSLProxy.h (source / functions) Hit Total Coverage
Test: app.info Lines: 2 6 33.3 %
Date: 2010-12-13 Functions: 1 4 25.0 %
Branches: 7 18 38.9 %

           Branch data     Line data    Source code
       1                 :            : // $Id: SSLProxy.h 5952 2008-07-13 19:45:15Z vern $
       2                 :            : 
       3                 :            : #ifndef SSLPROXY_H
       4                 :            : #define SSLPROXY_H
       5                 :            : 
       6                 :            : #include "TCP.h"
       7                 :            : #include "SSLInterpreter.h"
       8                 :            : #include "binpac_bro.h"
       9                 :            : 
      10                 :            : // --- forward declarations ---------------------------------------------------
      11                 :            : 
      12                 :            : class SSL_Interpreter;
      13                 :            : class SSL_RecordBuilder;
      14                 :            : class Contents_SSL;
      15                 :            : 
      16                 :            : // --- class SSL_DataBlock ----------------------------------------------------
      17                 :            : 
      18                 :            : /*!
      19                 :            :  * \brief This class is used to store a block of data on the heap, which is
      20                 :            :  *        allocated and copied by the constructor, and freed by the destructor.
      21                 :            :  *
      22                 :            :  * It is mainly used by the SSL_RecordBuilder to store the received data. To
      23                 :            :  * reduce heap operations (HeapOps), which can be quite expensive, it is
      24                 :            :  * possible to let the constructor allocate a minimum heap block size. The
      25                 :            :  * class members keep track of how much data has been allocated and how much of
      26                 :            :  * it has been used. Plus, there's a pointer to the next SSL_DataBlock, for
      27                 :            :  * easy creation of a single-linked list.
      28                 :            :  */
      29                 :            : 
      30                 :            : class SSL_DataBlock {
      31                 :            : public:
      32                 :            :         SSL_DataBlock(const u_char* data, int len, int min_len = 0);
      33                 :            : 
      34                 :            :         int len;        ///< The <b>used</b> size of the reserved heap block.
      35                 :            :         int size;       ///< The <b>allocated</b> size of the reserved heap block.
      36                 :            :         u_char* data;   ///< Pointer to the allocated heap block.
      37                 :            :         SSL_DataBlock* next;    ///< Pointer to the next SSL_Datablock in the chain.
      38                 :            : 
      39                 :            :         /*!
      40                 :            :          * The destructor will free the allocated data block.
      41                 :            :          */
      42         [ #  # ]:          0 :         ~SSL_DataBlock() { delete [] data; }
      43                 :            : 
      44                 :            :         void toStream(FILE* stream) const;
      45                 :            :         char* toString() const;
      46                 :            : };
      47                 :            : 
      48                 :            : // --- class SSL_RecordBuilder ------------------------------------------------
      49                 :            : 
      50                 :            : /*!
      51                 :            :  * \brief This class is used to reassemble SSL records from a stream of data.
      52                 :            :  *
      53                 :            :  * It supports both SSLv2 and SSLv3 record formats at the same time. The record
      54                 :            :  * builder has been designed to be robust, efficient and hard to attack. To add
      55                 :            :  * a segments of data, call addSegment(). Whenever a SSL record has been
      56                 :            :  * reassembled, the DoDeliver() function of the corresponding Contents_SSL
      57                 :            :  * will be called.
      58                 :            :  *
      59                 :            :  * Two forms of attack have been taken into consideration:
      60                 :            :  * -# The "fake size" attack, where the actual size of the SSL record is much
      61                 :            :  *    smaller then the size given in the record header. This way, an attacker
      62                 :            :  *    could force Bro to allocate a huge amount of memory and make it crash.
      63                 :            :  * -# The "small fragment" attack, where an attacker sends huge SSL records
      64                 :            :  *    in very small (1 byte or so) TCP segments. This could lead to a huge
      65                 :            :  *    amount of very small memory blocks allocated by Bro. After the last byte
      66                 :            :  *    of an SSL record has been received, all allocated blocks have to be
      67                 :            :  *    freed. Freeing something like 32K blocks of memory can be quite expensive,
      68                 :            :  *    so packet drops may occur, which could prevent Bro from detecting an
      69                 :            :  *    attacker.
      70                 :            :  *
      71                 :            :  * The current implementation always allocates a minimum size of data on the
      72                 :            :  * heap, which is MIN_ALLOC_SIZE. The processed SSL record fragments are stored
      73                 :            :  * in a single-linked list of type SSL_DataBlock.
      74                 :            :  *
      75                 :            :  * The following assumptions are made:
      76                 :            :  * - neededSize <= min( expectedSize )
      77                 :            :  * - neededSize <= MIN_ALLOC_SIZE, so the data needed to determine the SSL
      78                 :            :  *   record version fits in one SSL_DataBlock
      79                 :            :  */
      80                 :            : 
      81                 :            : class SSL_RecordBuilder {
      82                 :            : public:
      83                 :            :         SSL_RecordBuilder(Contents_SSL* sslEndpoint);
      84                 :            :         ~SSL_RecordBuilder();
      85                 :            : 
      86                 :            :         static const uint MIN_ALLOC_SIZE = 16;  ///< min. size of memory to alloc
      87                 :            :         static const int MIN_FRAGMENT_SIZE = 100;       ///< min. size of a middle TCP Segment
      88                 :            :         static uint maxAllocCount;      ///< max. number of allocated data blocks for an instance of a reassembler
      89                 :            :         static uint maxFragmentCount;   ///< max. number of fragments for a ssl record
      90                 :            :         static uint fragmentedHeaders;  ///< counter for the number of fragmented headers (header=neededSize)
      91                 :            : 
      92                 :            :         bool addSegment(const u_char* data, int length);
      93                 :            : 
      94                 :            :         /*!
      95                 :            :          * Calls this method to see if there's currently data in the
      96                 :            :          * record builder pending.
      97                 :            :          * \return true if there's data pending, false otherwise
      98                 :            :          */
      99                 :          0 :         bool isDataPending() { return hasPendingData; };
     100                 :            : 
     101                 :            : protected:
     102                 :            :         u_char* assembleBlocks(const u_char* data, int length);
     103                 :            :         int analyzeSSLRecordFormat(const u_char* data, int length);
     104                 :            :         bool computeExpectedSize (const u_char* data, int length);
     105                 :            :         void addData(const u_char* data, int length);
     106                 :            : 
     107                 :            :         SSL_DataBlock* head;    ///< pointer to the first element in the linked list of SSL_DataBlocks
     108                 :            :         SSL_DataBlock* tail;    ///< pointer to the last element in the linked list of SSL_DataBlocks
     109                 :            :         Contents_SSL*  sslEndpoint;     ///< pointer to the containing Contents_SSL
     110                 :            :         int  expectedSize;      ///< expected size of SSLv2 record including header
     111                 :            :         int  currentSize;       ///< current bytes stored in data blocks (that is, processed size of actual record)
     112                 :            :         int  neededSize;        ///< min. size in bytes so that the length of the current record can be determinded
     113                 :            :         bool hasPendingData;    ///< true if there's data following in the current tcp segment
     114                 :            :         uint fragmentCounter;   ///< counter for the number of tcp segments for the current record
     115                 :            : };
     116                 :            : 
     117                 :            : 
     118                 :            : // --- class SSLProxy_Analyzer ----------------------------------------------
     119                 :            : 
     120                 :            : /** This class represents an SSL_Connection with two SSL_ConnectionEndpoints.
     121                 :            :  * Note, that this class acts as a proxy, because there are different versions
     122                 :            :  * of the SSL protocol in use and you don't know in advance which SSL version
     123                 :            :  * really will be used. This depends on the first two messages of the SSL handshake
     124                 :            :  * process. Because Bro offers no possibility for switching connections we
     125                 :            :  * decided only to inherit this proxy from TCP_Connection.
     126                 :            :  * The different SSL versions are implemented in classed derived from
     127                 :            :  * SSL_Interpreter/SSL_InterpreterEndpoint and so, we can easily switch the flow
     128                 :            :  * of data to the appropriate SSL Interpreter.
     129                 :            :  * Currently, we support SSL Version 2.0 and 3.0/3.1(TLS)(@see SSLv2_Interpreter and @see
     130                 :            :  * SSLv3_Interpreter).
     131                 :            :  * This class holds an instance of both SSLv2- and SSLv3_Interpreter. The version
     132                 :            :  * of the SSL that is used for a connection is negotiated within the first
     133                 :            :  * two records (SSL messages): client hello and server hello.
     134                 :            :  * So after scanning this two records (which is mainly done in @see SSL_RecordBuilder and
     135                 :            :  * @see Contents_SSL) and determing the versions, it is clear which
     136                 :            :  * SSL version will be used for the succeding SSL records. From now
     137                 :            :  * on, they can be directly passed through to the appropriate SSL_Interpreter.
     138                 :            :  *
     139                 :            :  * FIXME: Now we have a dynamic analyzer framework so this could be restructured.
     140                 :            :  */
     141                 :            : class SSLProxy_Analyzer: public TCP_ApplicationAnalyzer {
     142                 :            : public:
     143                 :            :         SSLProxy_Analyzer(Connection* conn);
     144                 :            :         virtual ~SSLProxy_Analyzer();
     145                 :            : 
     146                 :            :         static uint totalPackets;       ///< counter for total ssl packets seen
     147                 :            :         static uint totalRecords;       ///< counter for total ssl records seen
     148                 :            :         static uint nonSSLConnections;  ///< counter for connections where we couldn't reassemble a ssl record
     149                 :            : 
     150                 :            :         static const bool recordSSLv2Traffic = false;   ///< if true, only recording of SSLv2 connections is done (no analysis)
     151                 :            : 
     152                 :            :         static bool bInited;
     153                 :            : 
     154                 :            :         enum SSL_Versions {
     155                 :            :                 SSLv20 = 0x0002,
     156                 :            :                 SSLv30 = 0x0300,
     157                 :            :                 SSLv31 = 0x0301  // = TLS 1.0
     158                 :            :         };
     159                 :            : 
     160                 :            :         /* This method is called from the corresponding Contents_SSL to
     161                 :            :          * deliver the data to the SSL_ProxyConnection. It decides which
     162                 :            :          * SSL_Interpreter (Version 2 or Version 3x) gets the record or
     163                 :            :          * directly passes it through, if it's already clear which version
     164                 :            :          * this SSL connection uses.
     165                 :            :          * @param endp the sending endpoint
     166                 :            :          * @param len length of SSL record
     167                 :            :          * @param data the SSL record
     168                 :            :          *
     169                 :            :          * SC mod  - pass a TCP_Contents rather than endpoint in terms of an actual
     170                 :            :          * Contents_SSL.  There is much less overall work to do since we
     171                 :            :          * have already done the assosciation.
     172                 :            :          */
     173                 :            :         void NewSSLRecord(Contents_SSL* endp, int len, const u_char* data);
     174                 :            : 
     175                 :            :         // Initialises the SSLv2- and SSLv3_Interpreters.
     176                 :            :         virtual void Init();
     177                 :            : 
     178                 :            :         // This method is used for passing messages to Bro that contain
     179                 :            :         // information about weaknesses in the choosen SSL encryption
     180                 :            :         // (short keys, unverifyable certificates, ...)
     181                 :            :         // @param name the name of the weakness.
     182                 :            :         void Weak(const char* name);
     183                 :            : 
     184                 :          0 :         static Analyzer* InstantiateAnalyzer(Connection* conn)
     185                 :          0 :                 { return new SSLProxy_Analyzer(conn); }
     186                 :            : 
     187                 :          1 :         static bool Available()
     188                 :            :                 {
     189                 :            :                 return (ssl_certificate_seen || ssl_certificate ||
     190                 :            :                         ssl_conn_attempt || ssl_conn_server_reply ||
     191                 :            :                         ssl_conn_established || ssl_conn_reused ||
     192                 :            :                         ssl_conn_alert)
     193 [ +  - ][ +  - ]:          1 :                         && ! FLAGS_use_binpac;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
     194                 :            :                 }
     195                 :            : 
     196                 :            :         static void printStats();
     197                 :            : 
     198                 :            : protected:
     199                 :            :         bool bPassThrough;      ///< whether it is clear which SSL version the connection will use
     200                 :            : 
     201                 :            :         SSL_Interpreter* sSLv2Interpreter;      ///< Interpreter for SSL version 2
     202                 :            :         SSL_Interpreter* sSLv3xInterpreter;     ///< Interpreter for SSL version 3.0 and 3.1
     203                 :            :         SSL_Interpreter* sSLInterpreter;        ///< Pointer to the interpreter currently in use
     204                 :            : 
     205                 :            :         Contents_SSL* sslpeo;
     206                 :            :         Contents_SSL* sslper;
     207                 :            : 
     208                 :            :         /** Internally called from this class Deliver()-method.
     209                 :            :          * It delivers the data to the correct corresponding
     210                 :            :          * SSL_InterpreterEndpoint.
     211                 :            :          * @param endp the sending endpoint
     212                 :            :          * @param t time, when the segment was received by bro (not used)
     213                 :            :          * @param seq relative sequenze number (from Endpoint::start_seq) (not used)
     214                 :            :          * @param len length of SSL record
     215                 :            :          * @param data the SSL record
     216                 :            :          */
     217                 :            :         void DoDeliver(int len, const u_char* data, bool orig);
     218                 :            : 
     219                 :            :         // Initialises the dictionary where the SSL cipher specs are stored.
     220                 :            :         // It needs only to be called once for a whole bro. @see SSLDefines.h
     221                 :            :         void BuildCipherDict();
     222                 :            : };
     223                 :            : 
     224                 :            : // --- class Contents_SSL ------------------------------------------------
     225                 :            : 
     226                 :            : /** This class represents an endpoint of a SSLProxy_Analyzer.
     227                 :            :  * It receives the new data (TCP segments) within the Deliver()-method, does
     228                 :            :  * some basic checks on the segment and passes it on to the SSL_RecordBuilder,
     229                 :            :  * which reassembles the segments into SSL records and determines the
     230                 :            :  * versions of the records. If the SSL_RecordBuilder was able to determine
     231                 :            :  * the versions of the records it delivers the reassembled records back tho this
     232                 :            :  * Contents_SSL by calling the DoDeliver()-method.
     233                 :            :  * The Contents_SSL then hands the record over to the corresponding
     234                 :            :  * SSLProxy_Analyzer by invoking it's NewSSLRecord()-method.
     235                 :            :  *
     236                 :            :  * SC mod: change class Contents_SSL: public TCP_EndpointContents
     237                 :            :  * to class Contents_SSL: public TCP_Contents
     238                 :            :  * this is done since the class uses the Deliver() method to take care of data.
     239                 :            :  *
     240                 :            :  */
     241                 :            : class Contents_SSL: public TCP_SupportAnalyzer {
     242                 :            : public:
     243                 :            :         /* The constructor builds up and initialises the Contents_SSL.
     244                 :            :          * @param conn the corresponding Connection
     245                 :            :          * @param whether this is the originator
     246                 :            :          */
     247                 :            :         Contents_SSL(Connection* conn, bool orig);
     248                 :            :         ~Contents_SSL();
     249                 :            : 
     250                 :            :         int sslRecordVersion;   ///< record version of the first SSL record seen (set by SSLProxy_Analyzer and SSL_RecordBuilder)
     251                 :            :         uint16 sslVersion;      ///< SSL version of the SSL record seen (set by SSL_RecordBuilder)
     252                 :            : 
     253                 :            :         /** Via this method, this Contents_SSL receives the
     254                 :            :          * TCP segments.
     255                 :            :          * @param len length of TCP-Segment
     256                 :            :          * @param data content of TCP-Segment
     257                 :            :          * @param orig whether sending endpoint is originator
     258                 :            :          */
     259                 :            :         virtual void DeliverStream(int len, const u_char* data, bool orig);
     260                 :            : 
     261                 :            :         /** This method is called by the corresponding SSL_RecordBuilder
     262                 :            :          * upon delivering a new reassembled SSL record.
     263                 :            :          * @param len the length of the record
     264                 :            :          * @param data the record
     265                 :            :          */
     266                 :            :         void DoDeliver(int len, const u_char* data);
     267                 :            : 
     268                 :            :         /* @return whether we have already seen the first record of the connection of this endpoint yet
     269                 :            :          */
     270                 :            :         bool VersionRecognized();
     271                 :            : 
     272                 :            :         /* @return whether the first record was of SSL version 2.0
     273                 :            :          */
     274                 :            :         bool IsSSLv2Record();
     275                 :            : 
     276                 :            :         /* @return whether the corresponding SSL_RecordBuilder has pending data
     277                 :            :          */
     278                 :            :         bool isDataPending(); // should be inline
     279                 :            : 
     280                 :            :         SSL_RecordBuilder* sslRecordBuilder;
     281                 :            : 
     282                 :            : protected:
     283                 :            :         bool bVersionRecognized;        ///< False, if we haven't seen the first record of the connection of this endpoint yet
     284                 :            :         bool bIsSSLv2Record;    ///< Was the first record of SSL version 2.0
     285                 :            : };
     286                 :            : 
     287                 :            : #endif

Generated by: LCOV version 1.8