Fix a buffer overflow found by Stefan Esser (untested).
authorgerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 16 Sep 2007 19:28:58 +0000 (19:28 +0000)
committergerald <gerald@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 16 Sep 2007 19:28:58 +0000 (19:28 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@22883 f5534014-38df-0310-8fa8-9805f1628bb7

docbook/release-notes.xml
epan/dissectors/packet-ssl-utils.h
epan/dissectors/packet-ssl.c

index a553ee9044f15b9a9c719d559ed9f0f2db1f0f04..f642cd07ff4ae73d9e5273b6f9dd8c7c3a6a0362 100644 (file)
@@ -59,6 +59,17 @@ Wireshark Info
           </para>
         </listitem>
 
+        <listitem>
+          <para>
+            Stefan Esser discovered a buffer overflow in the SSL dissector.
+            <!-- Fixed in r22883 -->
+          </para>
+          <para>Versions affected: 0.99.0 to 0.99.6</para>
+          <para>
+            <!-- <ulink url="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-????">CVE-2007-????</ulink> -->
+          </para>
+        </listitem>
+
       </itemizedlist>
 
     </para>
index 361ffa3ce2c077aff3068a882683ac6de08c84f0..4114fe314fd0bad246b15cdbf71f3b4e381d1386 100644 (file)
@@ -190,7 +190,7 @@ typedef struct _StringInfo {
 #define SSL_CLIENT_RANDOM       1
 #define SSL_SERVER_RANDOM       2
 #define SSL_CIPHER              4
-#define SSL_HAVE_SESSION_KEY    8    
+#define SSL_HAVE_SESSION_KEY    8
 #define SSL_VERSION             0x10
 #define SSL_MASTER_SECRET       0x20
 
@@ -199,6 +199,8 @@ typedef struct _StringInfo {
 
 #define SSL_DEBUG_USE_STDERR "-"
 
+#define SSLV2_MAX_SESSION_ID_LENGTH_IN_BYTES 16
+
 typedef struct _SslCipherSuite {
      gint number;
      gint kex;
@@ -271,7 +273,7 @@ typedef struct _SslDataInfo {
 
 typedef struct {
     SslDataInfo *appl_data;
-    SslRecordInfo* handshake_data; 
+    SslRecordInfo* handshake_data;
 } SslPacketInfo;
 
 typedef struct _SslDecryptSession {
@@ -288,7 +290,7 @@ typedef struct _SslDecryptSession {
     StringInfo server_data_for_iv;
     guchar _client_data_for_iv[24];
     StringInfo client_data_for_iv;
-    
+
     gint cipher;
     gint compression;
     gint state;
@@ -299,9 +301,9 @@ typedef struct _SslDecryptSession {
     SslDecoder *client_new;
     SSL_PRIVATE_KEY* private_key;
     guint32 version;
-    guint16 version_netorder;  
-    StringInfo app_data_segment; 
-  
+    guint16 version_netorder;
+    StringInfo app_data_segment;
+
 } SslDecryptSession;
 
 typedef struct _SslAssociation {
@@ -319,20 +321,20 @@ typedef struct _SslService {
 
 
 /** Initialize decryption engine/ssl layer. To be called once per execution */
-extern void 
+extern void
 ssl_lib_init(void);
 
 /** Initialize an ssl session struct
  @param ssl pointer to ssl session struct to be initialized */
-extern void 
+extern void
 ssl_session_init(SslDecryptSession* ssl);
 
 /** set the data and len for the stringInfo buffer. buf should be big enough to
  * contain the provided data
  @param buf the buffer to update
- @param src the data source 
+ @param src the data source
  @param len the source data len */
-extern void 
+extern void
 ssl_data_set(StringInfo* buf, const guchar* src, guint len);
 
 extern gint
@@ -341,29 +343,29 @@ ssl_cipher_setiv(SSL_CIPHER_CTX *cipher, guchar* iv, gint iv_len);
 /** Load an RSA private key from specified file
  @param fp the file that contain the key data
  @return a pointer to the loaded key on success, or NULL */
-extern SSL_PRIVATE_KEY* 
+extern SSL_PRIVATE_KEY*
 ssl_load_key(FILE* fp);
 
-/** Deallocate the memory used for specified key 
+/** Deallocate the memory used for specified key
  @param pointer to the key to be freed */
-extern void 
+extern void
 ssl_free_key(SSL_PRIVATE_KEY* key);
 
-/* Search for the specified cipher souite id 
- @param num the id of the cipher suite to be searched 
- @param cs pointer to the cipher suite struct to be filled 
+/* Search for the specified cipher souite id
+ @param num the id of the cipher suite to be searched
+ @param cs pointer to the cipher suite struct to be filled
  @return 0 if the cipher suite is found, -1 elsewhere */
-extern gint 
+extern gint
 ssl_find_cipher(int num,SslCipherSuite* cs);
 
-/* Expand the pre_master_secret to generate all the session information 
+/* Expand the pre_master_secret to generate all the session information
  * (master secret, session keys, ivs)
  @param ssl_session the store for all the session data
  @return 0 on success */
-extern gint 
+extern gint
 ssl_generate_keyring_material(SslDecryptSession*ssl_session);
 
-extern void 
+extern void
 ssl_change_cipher(SslDecryptSession *ssl_session, gboolean server);
 
 /* Try to decrypt in place the encrypted pre_master_secret
@@ -371,8 +373,8 @@ ssl_change_cipher(SslDecryptSession *ssl_session, gboolean server);
  @param entrypted_pre_master the rsa encrypted pre_master_secret
  @param pk the private key to be used for decryption
  @return 0 on success */
-extern gint 
-ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session, 
+extern gint
+ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
     StringInfo* entrypted_pre_master, SSL_PRIVATE_KEY *pk);
 
 /* Try to decrypt an ssl record
@@ -382,49 +384,49 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
  @param in a pinter to the ssl record to be decrypted
  @param inl the record lenght
  @param out a pointer to the store for the decrypted data
- @param outl the decrypted data len 
+ @param outl the decrypted data len
  @return 0 on success */
-extern gint 
-ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct, 
+extern gint
+ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
         const guchar* in, guint inl, StringInfo* comp_str, StringInfo* out_str, guint* outl);
 
 
 /* Common part bitween SSL and DTLS dissectors */
 /* Hash Functions for TLS/DTLS sessions table and private keys table */
-extern gint  
+extern gint
 ssl_equal (gconstpointer v, gconstpointer v2);
 
-extern guint 
+extern guint
 ssl_hash  (gconstpointer v);
 
-extern gint 
+extern gint
 ssl_private_key_equal (gconstpointer v, gconstpointer v2);
 
-extern guint 
+extern guint
 ssl_private_key_hash  (gconstpointer v);
 
 /* private key table entries have a scope 'larger' then packet capture,
  * so we can't relay on se_alloc** function */
-extern void 
+extern void
 ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_);
 
 /* handling of association between tls/dtls ports and clear text protocol */
-extern void 
+extern void
 ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, const gchar *protocol, gboolean tcp, gboolean from_key_list);
 
-extern void 
+extern void
 ssl_association_remove(GTree* associations, SslAssociation *assoc);
 
-extern gint 
+extern gint
 ssl_association_cmp(gconstpointer a, gconstpointer b);
 
-extern SslAssociation* 
+extern SslAssociation*
 ssl_association_find(GTree * associations, guint port, gboolean tcp);
 
-extern gint 
+extern gint
 ssl_assoc_from_key_list(gpointer key _U_, gpointer data, gpointer user_data);
 
-extern gint 
+extern gint
 ssl_packet_from_server(GTree* associations, guint port, gboolean tcp);
 
 /* add to packet data a newly allocated tvb with the specified real data*/
@@ -432,50 +434,50 @@ extern void
 ssl_add_record_info(gint proto, packet_info *pinfo, guchar* data, gint data_len, gint record_id);
 
 /* search in packet data the tvbuff associated to the specified id */
-extern tvbuff_t* 
+extern tvbuff_t*
 ssl_get_record_info(gint proto, packet_info *pinfo, gint record_id);
 
 void
 ssl_add_data_info(gint proto, packet_info *pinfo, guchar* data, gint data_len, gint key, SslFlow *flow);
 
-SslDataInfo* 
+SslDataInfo*
 ssl_get_data_info(int proto, packet_info *pinfo, gint key);
 
 /* initialize/reset per capture state data (ssl sessions cache) */
-extern void 
+extern void
 ssl_common_init(GHashTable **session_hash, StringInfo *decrypted_data, StringInfo *compressed_data);
 
 /* parse ssl related preferences (private keys and ports association strings) */
-extern void 
+extern void
 ssl_parse_key_list(const gchar * keys_list, GHashTable *key_hash, GTree* associations, dissector_handle_t handle, gboolean tcp);
 
 /* store master secret into session data cache */
-extern void 
+extern void
 ssl_save_session(SslDecryptSession* ssl, GHashTable *session_hash);
 
-extern void 
+extern void
 ssl_restore_session(SslDecryptSession* ssl, GHashTable *session_hash);
 
 extern gint
 ssl_is_valid_content_type(guint8 type);
 
 #ifdef SSL_DECRYPT_DEBUG
-extern void 
+extern void
 ssl_debug_printf(const gchar* fmt,...) GNUC_FORMAT_CHECK(printf,1,2);
-extern void 
+extern void
 ssl_print_data(const gchar* name, const guchar* data, gint len);
-extern void 
+extern void
 ssl_print_string(const gchar* name, const StringInfo* data);
-extern void 
+extern void
 ssl_print_text_data(const gchar* name, const guchar* data, gint len);
-extern void 
+extern void
 ssl_set_debug(gchar* name);
 #else
 
 /* No debug: nullify debug operation*/
 static inline void GNUC_FORMAT_CHECK(printf,1,2)
 ssl_debug_printf(const gchar* fmt _U_,...)
-{ 
+{
 }
 #define ssl_print_data(a, b, c)
 #define ssl_print_string(a, b)
index 18a89b61e35a4797b5af6eeadc3b7fead8f1a1b2..55efbd03cdf784d75cb94597abb06332d8350c53 100644 (file)
@@ -428,7 +428,7 @@ static gint dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
                                SslDecryptSession* ssl);
 
 /* client hello dissector */
-static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
+static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb, packet_info *pinfo,
                                           proto_tree *tree,
                                           guint32 offset,
                                           SslDecryptSession* ssl);
@@ -2687,7 +2687,7 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
         /* dissect the message (only handle client hello right now) */
         switch (msg_type) {
         case SSL2_HND_CLIENT_HELLO:
-            dissect_ssl2_hnd_client_hello(tvb, ssl_record_tree, offset, ssl);
+            dissect_ssl2_hnd_client_hello(tvb, pinfo, ssl_record_tree, offset, ssl);
             break;
 
         case SSL2_HND_CLIENT_MASTER_KEY:
@@ -2739,7 +2739,7 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 }
 
 static void
-dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
+dissect_ssl2_hnd_client_hello(tvbuff_t *tvb, packet_info *pinfo,
                               proto_tree *tree, guint32 offset,
                               SslDecryptSession* ssl)
 {
@@ -2791,6 +2791,15 @@ dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
         if (tree)
             proto_tree_add_item(tree, hf_ssl2_handshake_session_id_len,
                             tvb, offset, 2, FALSE);
+        if (session_id_length > SSLV2_MAX_SESSION_ID_LENGTH_IN_BYTES) {
+                proto_tree_add_text(tree, tvb, offset, 2,
+                    "Invalid session ID length: %d", session_id_length);
+                expert_add_info_format(pinfo, NULL, PI_MALFORMED, PI_ERROR,
+                    "Session ID length (%u) must be less than %u.",
+                    session_id_length, SSLV2_MAX_SESSION_ID_LENGTH_IN_BYTES);
+                offset = tvb_length(tvb);
+                return;
+        }
         offset += 2;
 
         challenge_length = tvb_get_ntohs(tvb, offset);