There's no need to allocate and fill in an array of sub-authorities and
[obnox/wireshark/wip.git] / packet-ssl.c
index 60e602732e765674115d5f65e55a743774de7b88..650e74c21a717e73c0b05a2f9e4780f9979bbb30 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for ssl dissection
  * Copyright (c) 2000-2001, Scott Renfro <scott@renfro.org>
  *
- * $Id: packet-ssl.c,v 1.5 2001/07/16 05:17:30 guy Exp $
+ * $Id: packet-ssl.c,v 1.22 2002/04/11 09:43:22 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 # include "snprintf.h"
 #endif
 
-#include "conversation.h"
+#include <epan/conversation.h>
+#include "prefs.h"
+
+static gboolean ssl_desegment = TRUE;
+
 
 /*********************************************************************
  *
@@ -85,6 +89,7 @@ static int hf_ssl2_record                    = -1;
 static int hf_ssl2_record_is_escape          = -1;
 static int hf_ssl2_record_padding_length     = -1;
 static int hf_ssl2_msg_type                  = -1;
+static int hf_pct_msg_type                   = -1;
 static int hf_ssl_change_cipher_spec         = -1;
 static int hf_ssl_alert_message              = -1;
 static int hf_ssl_alert_message_level        = -1;
@@ -147,12 +152,16 @@ static gint ett_ssl_dnames            = -1;
 
 /* The TCP port to associate with by default */
 #define TCP_PORT_SSL                    443
+#define TCP_PORT_SSL_LDAP               636
+#define TCP_PORT_SSL_IMAP               993
+#define TCP_PORT_SSL_POP                995
 
 /* version state tables */
 #define SSL_VER_UNKNOWN                   0
 #define SSL_VER_SSLv2                     1
 #define SSL_VER_SSLv3                     2
 #define SSL_VER_TLS                       3
+#define SSL_VER_PCT                       4
 
 /* corresponds to the #defines above */
 static gchar* ssl_version_short_names[] = {
@@ -160,6 +169,7 @@ static gchar* ssl_version_short_names[] = {
     "SSLv2",
     "SSLv3",
     "TLS",
+    "PCT"
 };
 
 /* other defines */
@@ -189,6 +199,14 @@ static gchar* ssl_version_short_names[] = {
 #define SSL2_HND_REQUEST_CERTIFICATE   0x07
 #define SSL2_HND_CLIENT_CERTIFICATE    0x08
 
+#define PCT_VERSION_1                 0x8001
+
+#define PCT_MSG_CLIENT_HELLO           0x01
+#define PCT_MSG_SERVER_HELLO           0x02
+#define PCT_MSG_CLIENT_MASTER_KEY      0x03
+#define PCT_MSG_SERVER_VERIFY          0x04
+#define PCT_MSG_ERROR                  0x05
+
 /*
  * Lookup tables
  *
@@ -214,6 +232,7 @@ static const value_string ssl_20_cipher_suites[] = {
     { 0x050080, "SSL2_IDEA_128_CBC_WITH_MD5" },
     { 0x060040, "SSL2_DES_64_CBC_WITH_MD5" },
     { 0x0700c0, "SSL2_DES_192_EDE3_CBC_WITH_MD5" },
+    { 0x080080, "SSL2_RC4_64_WITH_MD5" },
     { 0x000000, "TLS_NULL_WITH_NULL_NULL" },
     { 0x000001, "TLS_RSA_WITH_NULL_MD5" },
     { 0x000002, "TLS_RSA_WITH_NULL_SHA" },
@@ -245,11 +264,30 @@ static const value_string ssl_20_cipher_suites[] = {
     { 0x00001c, "SSL_FORTEZZA_KEA_WITH_NULL_SHA" },
     { 0x00001d, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA" },
     { 0x00001e, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA" },
+    { 0x000060, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5" },
+    { 0x000061, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5" },
     { 0x000062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA" },
     { 0x000063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA" },
     { 0x000064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA" },
     { 0x000065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA" },
     { 0x000066, "TLS_DHE_DSS_WITH_RC4_128_SHA" },
+    /* these from http://www.mozilla.org/projects/
+         security/pki/nss/ssl/fips-ssl-ciphersuites.html */
+    { 0x00fefe, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+    { 0x00feff, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+    { 0x00ffe0, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+    { 0x00ffe1, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+    /* Microsoft's old PCT protocol. These are from Eric Rescorla's
+       book "SSL and TLS" */
+    { 0x8f8001, "PCT_SSL_COMPAT | PCT_VERSION_1" },
+    { 0x800003, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509_CHAIN" },
+    { 0x800001, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509" },
+    { 0x810001, "PCT_SSL_HASH_TYPE | PCT1_HASH_MD5" },
+    { 0x810003, "PCT_SSL_HASH_TYPE | PCT1_HASH_SHA" },
+    { 0x820001, "PCT_SSL_EXCH_TYPE | PCT1_EXCH_RSA_PKCS1" },
+    { 0x830004, "PCT_SSL_CIPHER_TYPE_1ST_HALF | PCT1_CIPHER_RC4" },
+    { 0x848040, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_128 | PCT1_MAC_BITS_128" },
+    { 0x842840, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_40 | PCT1_MAC_BITS_128" },
     /* note that ciphersuites of {0x00????} are TLS cipher suites in
      * a sslv2 client hello message; the ???? above is the two-byte
      * tls cipher suite id
@@ -399,10 +437,26 @@ static const value_string ssl_31_ciphersuite[] = {
     { 0x0064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA" },
     { 0x0065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA" },
     { 0x0066, "TLS_DHE_DSS_WITH_RC4_128_SHA" },
+    /* these from http://www.mozilla.org/projects/
+         security/pki/nss/ssl/fips-ssl-ciphersuites.html */
+    { 0xfefe, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
+    { 0xfeff, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+    { 0xffe0, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
+    { 0xffe1, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
     /* note that ciphersuites 0xff00 - 0xffff are private */
     { 0x00, NULL }
 };
 
+static const value_string pct_msg_types[] = {
+    { PCT_MSG_CLIENT_HELLO,         "Client Hello" },
+    { PCT_MSG_SERVER_HELLO,         "Server Hello" },
+    { PCT_MSG_CLIENT_MASTER_KEY,    "Client Master Key" },
+    { PCT_MSG_SERVER_VERIFY,        "Server Verify" },
+    { PCT_MSG_ERROR,                "Error" },
+    { 0x00, NULL },
+};
+
+
 /*********************************************************************
  *
  * Forward Declarations
@@ -416,10 +470,11 @@ static const value_string ssl_31_ciphersuite[] = {
 /* record layer dissector */
 static int dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
                                proto_tree *tree, guint32 offset,
-                               guint *conv_version);
+                               guint *conv_version,
+                               gboolean *need_desegmentation);
 
 /* change cipher spec dissector */
-static void dissect_ssl3_change_cipher_spec(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
                                             proto_tree *tree,
                                             guint32 offset,
                                             guint *conv_version);
@@ -436,22 +491,22 @@ static void dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
                                    guint *conv_version);
 
 
-static void dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
                                        proto_tree *tree,
                                        guint32 offset);
 
-static void dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
                                        proto_tree *tree,
                                        guint32 offset);
 
-static void dissect_ssl3_hnd_cert(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_hnd_cert(tvbuff_t *tvb,
                                   proto_tree *tree, guint32 offset);
 
-static void dissect_ssl3_hnd_cert_req(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
                                       proto_tree *tree,
                                       guint32 offset);
 
-static void dissect_ssl3_hnd_finished(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl3_hnd_finished(tvbuff_t *tvb,
                                       proto_tree *tree,
                                       guint32 offset,
                                       guint *conv_version);
@@ -465,22 +520,21 @@ static void dissect_ssl3_hnd_finished(tvbuff_t *tvb, packet_info *pinfo,
 /* record layer dissector */
 static int dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
                                proto_tree *tree, guint32 offset,
-                               guint *conv_version);
+                               guint *conv_version,
+                               gboolean *need_desegmentation);
 
 /* client hello dissector */
-static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
                                           proto_tree *tree,
                                           guint32 offset);
 
 /* client master key dissector */
 static void dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
-                                               packet_info *pinfo,
                                                proto_tree *tree,
                                                guint32 offset);
 
 /* server hello dissector */
 static void dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
-                                          packet_info *pinfo,
                                           proto_tree *tree,
                                           guint32 offset);
 
@@ -500,6 +554,9 @@ static int  ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset);
 static int  ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
                                               guint32 offset,
                                               guint32 record_length);
+static int  ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
+                                               guint32 offset,
+                                               guint32 record_length);
 
 /*********************************************************************
  *
@@ -514,11 +571,13 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
 
     conversation_t *conversation;
+    void *conv_data;
     guint conv_version     = SSL_VER_UNKNOWN;
     proto_item *ti         = NULL;
     proto_tree *ssl_tree   = NULL;
     guint32 offset         = 0;
     gboolean first_record_in_frame = TRUE;
+    gboolean need_desegmentation;
 
     /* Track the version using conversations to reduce the
      * chance that a packet that simply *looks* like a v2 or
@@ -538,25 +597,25 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     {
         /* create a new conversation */
         conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
-                                        pinfo->srcport, pinfo->destport,
-                                        (void*)SSL_VER_UNKNOWN, 0);
+                                        pinfo->srcport, pinfo->destport, 0);
     }
-    if (conversation)
+    conv_data = conversation_get_proto_data(conversation, proto_ssl);
+    if (conv_data != NULL)
     {
-        conv_version = (guint)conversation->data;
+        conv_version = (guint)conv_data;
     }
 
     /* Initialize the protocol column; we'll set it later when we
      * figure out what flavor of SSL it is (assuming we don't
      * throw an exception before we get the chance to do so). */
-    if (check_col(pinfo->fd, COL_PROTOCOL))
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
     {
-        col_set_str(pinfo->fd, COL_PROTOCOL, "SSL");
+        col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSL");
     }
 
     /* clear the the info column */
-    if (check_col(pinfo->fd, COL_INFO))
-        col_clear(pinfo->fd, COL_INFO);
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_clear(pinfo->cinfo, COL_INFO);
 
     /* TCP packets and SSL records are orthogonal.
      * A tcp packet may contain multiple ssl records and an ssl
@@ -575,30 +634,36 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     /* Create display subtree for SSL as a whole */
     if (tree)
     {
-        ti = proto_tree_add_item(tree, proto_ssl, tvb,
-                                 0, tvb_length(tvb), FALSE);
+        ti = proto_tree_add_item(tree, proto_ssl, tvb, 0, -1, FALSE);
         ssl_tree = proto_item_add_subtree(ti, ett_ssl);
     }
 
-    /* iterate through the records in this frame */
-    while (offset < tvb_length(tvb)-1)
+    /* iterate through the records in this tvbuff */
+    while (tvb_reported_length_remaining(tvb, offset) != 0)
     {
         /* on second and subsequent records per frame
          * add a delimiter on info column
          */
         if (!first_record_in_frame
-            && check_col(pinfo->fd, COL_INFO))
+            && check_col(pinfo->cinfo, COL_INFO))
         {
-            col_append_str(pinfo->fd, COL_INFO, ", ");
+            col_append_str(pinfo->cinfo, COL_INFO, ", ");
         }
 
+       /*
+        * Assume, for now, that this doesn't need desegmentation.
+        */
+       need_desegmentation = FALSE;
+
         /* first try to dispatch off the cached version
          * known to be associated with the conversation
          */
         switch(conv_version) {
         case SSL_VER_SSLv2:
+        case SSL_VER_PCT:
             offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
-                                         offset, &conv_version);
+                                         offset, &conv_version,
+                                         &need_desegmentation);
             break;
 
         case SSL_VER_SSLv3:
@@ -612,12 +677,14 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             if (ssl_is_v2_client_hello(tvb, offset))
             {
                 offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
-                                             offset, &conv_version);
+                                             offset, &conv_version,
+                                             &need_desegmentation);
             }
             else
             {
                 offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
-                                             offset, &conv_version);
+                                             offset, &conv_version,
+                                             &need_desegmentation);
             }
             break;
 
@@ -627,15 +694,17 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         default:
             if (ssl_looks_like_sslv2(tvb, offset))
             {
-                /* looks like sslv2 client hello */
+                /* looks like sslv2 or pct client hello */
                 offset = dissect_ssl2_record(tvb, pinfo, ssl_tree,
-                                             offset, &conv_version);
+                                             offset, &conv_version,
+                                             &need_desegmentation);
             }
             else if (ssl_looks_like_sslv3(tvb, offset))
             {
                 /* looks like sslv3 or tls */
                 offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
-                                             offset, &conv_version);
+                                             offset, &conv_version,
+                                             &need_desegmentation);
             }
             else
             {
@@ -643,22 +712,33 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                  * continuation data
                  */
                 offset = tvb_length(tvb);
-                if (check_col(pinfo->fd, COL_INFO))
-                    col_append_str(pinfo->fd, COL_INFO,
+                if (check_col(pinfo->cinfo, COL_INFO))
+                    col_append_str(pinfo->cinfo, COL_INFO,
                                    "Continuation Data");
 
                 /* Set the protocol column */
-                if (check_col(pinfo->fd, COL_PROTOCOL))
+                if (check_col(pinfo->cinfo, COL_PROTOCOL))
                 {
-                    col_set_str(pinfo->fd, COL_PROTOCOL,
+                    col_set_str(pinfo->cinfo, COL_PROTOCOL,
                          ssl_version_short_names[conv_version]);
                 }
             }
             break;
         }
 
+        /* Desegmentation return check */
+        if (need_desegmentation)
+          return;
+
+        /* If we haven't already set the version information for
+         * this conversation, do so. */
+        if (conv_data == NULL)
+        {
+            conv_data = (void *)conv_version;
+            conversation_add_proto_data(conversation, proto_ssl, conv_data);
+        }
+
         /* set up for next record in frame, if any */
-        conversation->data = (void*)conv_version;
         first_record_in_frame = FALSE;
     }
 
@@ -673,7 +753,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 static int
 dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
                     proto_tree *tree, guint32 offset,
-                    guint *conv_version)
+                    guint *conv_version, gboolean *need_desegmentation)
 {
 
     /*
@@ -700,6 +780,29 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
     guint8 next_byte;
     proto_tree *ti              = NULL;
     proto_tree *ssl_record_tree = NULL;
+    guint32 available_bytes     = 0;
+
+    available_bytes = tvb_length_remaining(tvb, offset);
+
+    /*
+     * Can we do reassembly?
+     */
+    if (ssl_desegment && pinfo->can_desegment) {
+        /*
+         * Yes - is the record header split across segment boundaries?
+         */
+        if (available_bytes < 5) {
+            /*
+             * Yes.  Tell the TCP dissector where the data for this
+             * message starts in the data it handed us, and how many
+             * more bytes we need, and return.
+             */
+            pinfo->desegment_offset = offset;
+            pinfo->desegment_len = 5 - available_bytes;
+            *need_desegmentation = TRUE;
+            return offset;
+        }
+    }
 
     /*
      * Get the record layer fields of interest
@@ -708,18 +811,40 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
     version       = tvb_get_ntohs(tvb, offset + 1);
     record_length = tvb_get_ntohs(tvb, offset + 3);
 
+    if (ssl_is_valid_content_type(content_type)) {
+
+        /*
+         * Can we do reassembly?
+         */
+        if (ssl_desegment && pinfo->can_desegment) {
+            /*
+             * Yes - is the record split across segment boundaries?
+             */
+            if (available_bytes < record_length + 5) {
+                /*
+                 * Yes.  Tell the TCP dissector where the data for this
+                 * message starts in the data it handed us, and how many
+                 * more bytes we need, and return.
+                 */
+                pinfo->desegment_offset = offset;
+                pinfo->desegment_len = (record_length + 5) - available_bytes;
+                *need_desegmentation = TRUE;
+                return offset;
+            }
+        }
+      
+    } else {
+      
     /* if we don't have a valid content_type, there's no sense
      * continuing any further
      */
-    if (!ssl_is_valid_content_type(content_type))
-    {
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Continuation Data");
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Continuation Data");
 
         /* Set the protocol column */
-        if (check_col(pinfo->fd, COL_PROTOCOL))
+        if (check_col(pinfo->cinfo, COL_PROTOCOL))
         {
-            col_set_str(pinfo->fd, COL_PROTOCOL,
+            col_set_str(pinfo->cinfo, COL_PROTOCOL,
                         ssl_version_short_names[*conv_version]);
         }
         return offset + 5 + record_length;
@@ -782,21 +907,21 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
             ssl_set_conv_version(pinfo, *conv_version);
         }
     }
-    if (check_col(pinfo->fd, COL_PROTOCOL))
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
     {
         if (version == 0x0300)
         {
-            col_set_str(pinfo->fd, COL_PROTOCOL,
+            col_set_str(pinfo->cinfo, COL_PROTOCOL,
                         ssl_version_short_names[SSL_VER_SSLv3]);
         }
         else if (version == 0x0301)
         {
-            col_set_str(pinfo->fd, COL_PROTOCOL,
+            col_set_str(pinfo->cinfo, COL_PROTOCOL,
                         ssl_version_short_names[SSL_VER_TLS]);
         }
         else
         {
-            col_set_str(pinfo->fd, COL_PROTOCOL,
+            col_set_str(pinfo->cinfo, COL_PROTOCOL,
                         ssl_version_short_names[*conv_version]);
         }
     }
@@ -806,9 +931,9 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
      */
     switch (content_type) {
     case SSL_ID_CHG_CIPHER_SPEC:
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Change Cipher Spec");
-        dissect_ssl3_change_cipher_spec(tvb, pinfo, ssl_record_tree,
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
+        dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree,
                                         offset, conv_version);
         break;
     case SSL_ID_ALERT:
@@ -820,8 +945,8 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
                                record_length, conv_version);
         break;
     case SSL_ID_APP_DATA:
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Application Data");
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Application Data");
         if (ssl_record_tree)
         {
             proto_item_set_text(ssl_record_tree,
@@ -834,8 +959,8 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
 
     default:
         /* shouldn't get here since we check above for valid types */
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Bad SSLv3 Content Type");
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Bad SSLv3 Content Type");
         break;
     }
     offset += record_length; /* skip to end of record */
@@ -845,7 +970,7 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
 
 /* dissects the change cipher spec procotol, filling in the tree */
 static void
-dissect_ssl3_change_cipher_spec(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
                                 proto_tree *tree, guint32 offset,
                                 guint *conv_version)
 {
@@ -902,15 +1027,15 @@ dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
     /* now set the text in the record layer line */
     if (level && desc)
     {
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_fstr(pinfo->fd, COL_INFO,
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_fstr(pinfo->cinfo, COL_INFO,
                             "Alert (Level: %s, Description: %s)",
                             level, desc);
     }
     else
     {
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Encrypted Alert");
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Alert");
     }
 
     if (tree)
@@ -997,15 +1122,15 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
         /* on second and later iterations, add comma to info col */
         if (!first_iteration)
         {
-            if (check_col(pinfo->fd, COL_INFO))
-                col_append_fstr(pinfo->fd, COL_INFO, ", ");
+            if (check_col(pinfo->cinfo, COL_INFO))
+                col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
         }
 
         /*
          * Update our info string
          */
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_fstr(pinfo->fd, COL_INFO, "%s", (msg_type_str != NULL)
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_fstr(pinfo->cinfo, COL_INFO, "%s", (msg_type_str != NULL)
                             ? msg_type_str : "Encrypted Handshake Message");
 
         if (tree)
@@ -1062,19 +1187,19 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
                 break;
 
             case SSL_HND_CLIENT_HELLO:
-                dissect_ssl3_hnd_cli_hello(tvb, pinfo, ssl_hand_tree, offset);
+                dissect_ssl3_hnd_cli_hello(tvb, ssl_hand_tree, offset);
             break;
 
             case SSL_HND_SERVER_HELLO:
-                dissect_ssl3_hnd_srv_hello(tvb, pinfo, ssl_hand_tree, offset);
+                dissect_ssl3_hnd_srv_hello(tvb, ssl_hand_tree, offset);
                 break;
 
             case SSL_HND_CERTIFICATE:
-                dissect_ssl3_hnd_cert(tvb, pinfo, ssl_hand_tree, offset);
+                dissect_ssl3_hnd_cert(tvb, ssl_hand_tree, offset);
                 break;
 
             case SSL_HND_CERT_REQUEST:
-                dissect_ssl3_hnd_cert_req(tvb, pinfo, ssl_hand_tree, offset);
+                dissect_ssl3_hnd_cert_req(tvb, ssl_hand_tree, offset);
                 break;
 
             case SSL_HND_SVR_HELLO_DONE:
@@ -1082,7 +1207,7 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
                 break;
 
             case SSL_HND_FINISHED:
-                dissect_ssl3_hnd_finished(tvb, pinfo, ssl_hand_tree,
+                dissect_ssl3_hnd_finished(tvb, ssl_hand_tree,
                                           offset, conv_version);
                 break;
 
@@ -1109,14 +1234,14 @@ dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
 {
     /* show the client's random challenge */
     guint32 initial_offset = offset;
-    struct timeval gmt_unix_time;
+    nstime_t gmt_unix_time;
     guint8  session_id_length = 0;
 
     if (tree)
     {
         /* show the time */
-        gmt_unix_time.tv_sec = tvb_get_ntohl(tvb, offset);
-        gmt_unix_time.tv_usec = 0;
+        gmt_unix_time.secs = tvb_get_ntohl(tvb, offset);
+        gmt_unix_time.nsecs = 0;
         proto_tree_add_time(tree, hf_ssl_handshake_random_time,
                                      tvb, offset, 4, &gmt_unix_time);
         offset += 4;
@@ -1146,7 +1271,7 @@ dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
 }
 
 static void
-dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
                            proto_tree *tree, guint32 offset)
 {
     /* struct {
@@ -1239,7 +1364,7 @@ dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
                            proto_tree *tree, guint32 offset)
 {
     /* struct {
@@ -1275,7 +1400,7 @@ dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl3_hnd_cert(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_hnd_cert(tvbuff_t *tvb,
                       proto_tree *tree, guint32 offset)
 {
 
@@ -1339,7 +1464,7 @@ dissect_ssl3_hnd_cert(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl3_hnd_cert_req(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
                           proto_tree *tree, guint32 offset)
 {
     /*
@@ -1435,7 +1560,7 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl3_hnd_finished(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl3_hnd_finished(tvbuff_t *tvb,
                           proto_tree *tree, guint32 offset,
                           guint *conv_version)
 {
@@ -1483,53 +1608,90 @@ dissect_ssl3_hnd_finished(tvbuff_t *tvb, packet_info *pinfo,
 
 /* record layer dissector */
 static int
-dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree
-                    *tree, guint32 offset, guint *conv_version)
+dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                    guint32 offset, guint *conv_version,
+                    gboolean *need_desegmentation)
 {
     guint32 initial_offset       = offset;
     guint8  byte                 = 0;
     guint8  record_length_length = 0;
-    gint32  record_length        = -1;
+    guint32 record_length        = 0;
     gint    is_escape            = -1;
     gint16  padding_length       = -1;
     guint8  msg_type             = 0;
     gchar   *msg_type_str        = NULL;
+    guint32 available_bytes      = 0;
 
     proto_tree *ti;
     proto_tree *ssl_record_tree = NULL;
 
-    /* if we get here, but don't have a version set for the
-     * conversation, then set a version for just this frame
-     * (e.g., on a client hello)
-     */
-    if (check_col(pinfo->fd, COL_PROTOCOL))
-    {
-        col_set_str(pinfo->fd, COL_PROTOCOL, "SSLv2");
-    }
-
     /* pull first byte; if high bit is set, then record
      * length is three bytes due to padding; otherwise
      * record length is two bytes
      */
-    byte = tvb_get_guint8(tvb, offset++);
+    byte = tvb_get_guint8(tvb, offset);
     record_length_length = (byte & 0x80) ? 2 : 3;
 
+    /*
+     * Can we do reassembly?
+     */
+    available_bytes = tvb_length_remaining(tvb, offset);
+
+    if (ssl_desegment && pinfo->can_desegment) {
+        /*
+         * Yes - is the record header split across segment boundaries?
+         */
+        if (available_bytes < record_length_length) {
+            /*
+             * Yes.  Tell the TCP dissector where the data for this
+             * message starts in the data it handed us, and how many
+             * more bytes we need, and return.
+             */
+            pinfo->desegment_offset = offset;
+            pinfo->desegment_len = record_length_length - available_bytes;
+            *need_desegmentation = TRUE;
+            return offset;
+        }
+    }
+
     /* parse out the record length */
     switch(record_length_length) {
     case 2:                     /* two-byte record length */
         record_length = (byte & 0x7f) << 8;
-        byte = tvb_get_guint8(tvb, offset++);
+        byte = tvb_get_guint8(tvb, offset + 1);
         record_length += byte;
         break;
     case 3:                     /* three-byte record length */
         is_escape = (byte & 0x40) ? TRUE : FALSE;
         record_length = (byte & 0x3f) << 8;
-        byte = tvb_get_guint8(tvb, offset++);
+        byte = tvb_get_guint8(tvb, offset + 1);
         record_length += byte;
-        byte = tvb_get_guint8(tvb, offset++);
+        byte = tvb_get_guint8(tvb, offset + 2);
         padding_length = byte;
     }
 
+    /*
+     * Can we do reassembly?
+     */
+    if (ssl_desegment && pinfo->can_desegment) {
+        /*
+         * Yes - is the record split across segment boundaries?
+         */
+        if (available_bytes < (record_length_length + record_length)) {
+            /*
+             * Yes.  Tell the TCP dissector where the data for this
+             * message starts in the data it handed us, and how many
+             * more bytes we need, and return.
+             */
+            pinfo->desegment_offset = offset;
+            pinfo->desegment_len = (record_length_length + record_length)
+                                  - available_bytes;
+            *need_desegmentation = TRUE;
+            return offset;
+        }
+    }
+    offset += record_length_length;
+
     /* add the record layer subtree header */
     ti = proto_tree_add_item(tree, hf_ssl2_record, tvb, initial_offset,
                              record_length_length + record_length, 0);
@@ -1541,39 +1703,69 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree
     /* if we get a server_hello or later handshake in v2, then set
      * this to sslv2
      */
-    if (*conv_version == SSL_VER_UNKNOWN
-        && msg_type >= 2 && msg_type <= 8)
+    if (*conv_version == SSL_VER_UNKNOWN)
+    {
+        if (ssl_looks_like_valid_pct_handshake(tvb,
+                                               (initial_offset +
+                                                record_length_length),
+                                               record_length)) {
+            *conv_version = SSL_VER_PCT;
+            ssl_set_conv_version(pinfo, *conv_version);
+        }
+        else if (msg_type >= 2 && msg_type <= 8)
+        {
+            *conv_version = SSL_VER_SSLv2;
+            ssl_set_conv_version(pinfo, *conv_version);
+        }
+    }
+    
+    /* if we get here, but don't have a version set for the
+     * conversation, then set a version for just this frame
+     * (e.g., on a client hello)
+     */
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
     {
-        *conv_version = SSL_VER_SSLv2;
-        ssl_set_conv_version(pinfo, *conv_version);
+        col_set_str(pinfo->cinfo, COL_PROTOCOL,
+                    (*conv_version == SSL_VER_PCT) ? "PCT" : "SSLv2");
     }
 
     /* see if the msg_type is valid; if not the payload is
      * probably encrypted, so note that fact and bail
      */
-    msg_type_str = match_strval(msg_type, ssl_20_msg_types);
+    msg_type_str = match_strval(msg_type,
+                                (*conv_version == SSL_VER_PCT)
+                               ? pct_msg_types : ssl_20_msg_types);
     if (!msg_type_str
-        || !ssl_looks_like_valid_v2_handshake(tvb, initial_offset
-                                              + record_length_length,
-                                              record_length))
+        || ((*conv_version != SSL_VER_PCT) &&
+           !ssl_looks_like_valid_v2_handshake(tvb, initial_offset
+                                              + record_length_length,
+                                              record_length))
+       || ((*conv_version == SSL_VER_PCT) &&
+           !ssl_looks_like_valid_pct_handshake(tvb, initial_offset
+                                               + record_length_length,
+                                               record_length)))
     {
         if (ssl_record_tree)
         {
-            proto_item_set_text(ssl_record_tree, "SSLv2 Record Layer: %s",
+            proto_item_set_text(ssl_record_tree, "%s Record Layer: %s",
+                                (*conv_version == SSL_VER_PCT)
+                                ? "PCT" : "SSLv2",
                                 "Encrypted Data");
         }
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, "Encrypted Data");
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Data");
         return initial_offset + record_length_length + record_length;
     }
     else
     {
-        if (check_col(pinfo->fd, COL_INFO))
-            col_append_str(pinfo->fd, COL_INFO, msg_type_str);
+        if (check_col(pinfo->cinfo, COL_INFO))
+            col_append_str(pinfo->cinfo, COL_INFO, msg_type_str);
 
         if (ssl_record_tree)
         {
-            proto_item_set_text(ssl_record_tree, "SSLv2 Record Layer: %s",
+            proto_item_set_text(ssl_record_tree, "%s Record Layer: %s",
+                                (*conv_version == SSL_VER_PCT)
+                                ? "PCT" : "SSLv2",
                                 msg_type_str);
         }
     }
@@ -1582,7 +1774,7 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree
      * tree by adding the length, is_escape boolean and padding_length,
      * if present in the original packet
      */
-    if (ssl_record_tree && record_length != -1)
+    if (ssl_record_tree)
     {
         /* add the record length */
         ti = proto_tree_add_uint (ssl_record_tree,
@@ -1613,45 +1805,63 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree
     /* add the message type */
     if (ssl_record_tree)
     {
-        proto_tree_add_item(ssl_record_tree, hf_ssl2_msg_type, tvb,
-                            offset, 1, 0);
+        proto_tree_add_item(ssl_record_tree,
+                            (*conv_version == SSL_VER_PCT)
+                            ? hf_pct_msg_type : hf_ssl2_msg_type,
+                            tvb, offset, 1, 0);
     }
     offset++;                   /* move past msg_type byte */
 
+    if (*conv_version != SSL_VER_PCT)
+    {
+        /* 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);
+            break;
 
-    /* dissect the message (only handle client hello right now) */
-    switch (msg_type) {
-    case SSL2_HND_CLIENT_HELLO:
-        dissect_ssl2_hnd_client_hello(tvb, pinfo, ssl_record_tree, offset);
-        break;
-
-    case SSL2_HND_CLIENT_MASTER_KEY:
-        dissect_ssl2_hnd_client_master_key(tvb, pinfo, ssl_record_tree, offset);
-        break;
+        case SSL2_HND_CLIENT_MASTER_KEY:
+            dissect_ssl2_hnd_client_master_key(tvb, ssl_record_tree, offset);
+            break;
 
-    case SSL2_HND_SERVER_HELLO:
-        dissect_ssl2_hnd_server_hello(tvb, pinfo, ssl_record_tree, offset);
-        break;
+        case SSL2_HND_SERVER_HELLO:
+            dissect_ssl2_hnd_server_hello(tvb, ssl_record_tree, offset);
+            break;
 
-    case SSL2_HND_ERROR:
-    case SSL2_HND_CLIENT_FINISHED:
-    case SSL2_HND_SERVER_VERIFY:
-    case SSL2_HND_SERVER_FINISHED:
-    case SSL2_HND_REQUEST_CERTIFICATE:
-    case SSL2_HND_CLIENT_CERTIFICATE:
-        /* unimplemented */
-        break;
+        case SSL2_HND_ERROR:
+        case SSL2_HND_CLIENT_FINISHED:
+        case SSL2_HND_SERVER_VERIFY:
+        case SSL2_HND_SERVER_FINISHED:
+        case SSL2_HND_REQUEST_CERTIFICATE:
+        case SSL2_HND_CLIENT_CERTIFICATE:
+            /* unimplemented */
+            break;
 
-    default:                    /* unknown */
-        break;
+        default:                    /* unknown */
+            break;
+        }
     }
+    else
+    {
+        /* dissect the message */ 
+        switch (msg_type) {
+        case PCT_MSG_CLIENT_HELLO:
+        case PCT_MSG_SERVER_HELLO:
+        case PCT_MSG_CLIENT_MASTER_KEY:
+        case PCT_MSG_SERVER_VERIFY:
+        case PCT_MSG_ERROR:
+            /* unimplemented */
+            break;
 
-
+        default:                    /* unknown */
+            break;
+        }
+    }
     return (initial_offset + record_length_length + record_length);
 }
 
 static void
-dissect_ssl2_hnd_client_hello(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
                               proto_tree *tree, guint32 offset)
 {
     /* struct {
@@ -1752,7 +1962,7 @@ dissect_ssl2_hnd_client_hello(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
                                    proto_tree *tree, guint32 offset)
 {
     /* struct {
@@ -1826,7 +2036,7 @@ dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb, packet_info *pinfo,
 }
 
 static void
-dissect_ssl2_hnd_server_hello(tvbuff_t *tvb, packet_info *pinfo,
+dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
                               proto_tree *tree, guint32 offset)
 {
     /* struct {
@@ -1957,19 +2167,31 @@ static void
 ssl_set_conv_version(packet_info *pinfo, guint version)
 {
     conversation_t *conversation;
+
+    if (pinfo->fd->flags.visited)
+    {
+        /* We've already processed this frame; no need to do any more
+         * work on it.
+         */
+        return;
+    }
+
     conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
                                      pinfo->srcport, pinfo->destport, 0);
 
-    if (conversation)
+    if (conversation == NULL)
     {
-        conversation->data = (void*)version;
+        /* create a new conversation */
+        conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
+                                        pinfo->srcport, pinfo->destport, 0);
     }
-    else
+
+    if (conversation_get_proto_data(conversation, proto_ssl) != NULL)
     {
-        /* create a new conversation */
-        conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
-                         pinfo->srcport, pinfo->destport, (void*)version, 0);
+        /* get rid of the current data */
+        conversation_delete_proto_data(conversation, proto_ssl);
     }
+    conversation_add_proto_data(conversation, proto_ssl, (void *)version);
 }
 
 static int
@@ -2081,6 +2303,8 @@ ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
     case SSL2_HND_CLIENT_HELLO:
     case SSL2_HND_CLIENT_MASTER_KEY:
     case SSL2_HND_SERVER_HELLO:
+    case PCT_MSG_CLIENT_MASTER_KEY:
+    case PCT_MSG_ERROR:
         return 1;
     }
     return 0;
@@ -2178,6 +2402,78 @@ ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb, guint32 offset,
     return 0;
 }
 
+/* applies a heuristic to determine whether
+ * or not the data beginning at offset looks
+ * like a valid, unencrypted v2 handshake message.
+ * since it isn't possible to completely tell random
+ * data apart from a valid message without state,
+ * we try to help the odds.
+ */
+static int
+ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, guint32 offset,
+                                  guint32 record_length)
+{
+    /* first byte should be a msg_type.
+     *
+     *   - we know we only see client_hello, client_master_key,
+     *     and server_hello in the clear, so check to see if
+     *     msg_type is one of those (this gives us a 3 in 2^8
+     *     chance of saying yes with random payload)
+     *
+     *   - for those three types that we know about, do some
+     *     further validation to reduce the chance of an error
+     */
+    guint8 msg_type;
+    guint16 version;
+    guint32 sum;
+
+    /* fetch the msg_type */
+    msg_type = tvb_get_guint8(tvb, offset);
+
+    switch (msg_type) {
+    case PCT_MSG_CLIENT_HELLO:
+        /* version follows msg byte, so verify that this is valid */
+        version = tvb_get_ntohs(tvb, offset+1);
+        return version == PCT_VERSION_1;
+        break;
+
+    case PCT_MSG_SERVER_HELLO:
+        /* version is one byte after msg_type */
+        version = tvb_get_ntohs(tvb, offset+2);
+        return version == PCT_VERSION_1;
+        break;
+
+    case PCT_MSG_CLIENT_MASTER_KEY:
+        /* sum of various length fields must be less than record length */
+        sum  = tvb_get_ntohs(tvb, offset + 6); /* clear_key_length */
+        sum += tvb_get_ntohs(tvb, offset + 8); /* encrypted_key_length */
+        sum += tvb_get_ntohs(tvb, offset + 10); /* key_arg_length */
+        sum += tvb_get_ntohs(tvb, offset + 12); /* verify_prelude_length */
+        sum += tvb_get_ntohs(tvb, offset + 14); /* client_cert_length */
+        sum += tvb_get_ntohs(tvb, offset + 16); /* response_length */
+        if (sum > record_length)
+        {
+            return 0;
+        }
+        return 1;
+        break;
+
+    case PCT_MSG_SERVER_VERIFY:
+       /* record is 36 bytes longer than response_length */
+       sum = tvb_get_ntohs(tvb, offset + 34); /* response_length */
+       if ((sum + 36) == record_length)
+           return 1;
+       else
+           return 0;
+       break;
+
+    default:
+        return 0;
+    }
+    return 0;
+}
+
+
 /*********************************************************************
  *
  * Standard Ethereal Protocol Registration and housekeeping
@@ -2204,6 +2500,11 @@ proto_register_ssl(void)
             FT_UINT8, BASE_DEC, VALS(ssl_20_msg_types), 0x0,
             "SSLv2 handshake message type", HFILL}
         },
+        { &hf_pct_msg_type,
+          { "Handshake Message Type", "ssl.pct_handshake.type",
+            FT_UINT8, BASE_DEC, VALS(pct_msg_types), 0x0,
+            "PCT handshake message type", HFILL}
+        },
         { &hf_ssl_record_version,
           { "Version", "ssl.record.version",
             FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
@@ -2220,9 +2521,9 @@ proto_register_ssl(void)
             "Payload is application data", HFILL }
         },
         { & hf_ssl2_record,
-          { "SSLv2 Record Header", "ssl.record",
+          { "SSLv2/PCT Record Header", "ssl.record",
             FT_NONE, BASE_DEC, NULL, 0x0,
-            "SSLv2 record data", HFILL }
+            "SSLv2/PCT record data", HFILL }
         },
         { &hf_ssl2_record_is_escape,
           { "Is Escape", "ssl.record.is_escape",
@@ -2497,6 +2798,18 @@ proto_register_ssl(void)
      * subtrees used */
     proto_register_field_array(proto_ssl, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
+
+    {
+      module_t *ssl_module = prefs_register_protocol(proto_ssl, NULL);
+      prefs_register_bool_preference(ssl_module,
+                                     "desegment_ssl_records",
+                                     "Desegment SSL records",
+                                     "When enabled, SSL records that span multiple TCP segments are desegmented",
+                                     &ssl_desegment);
+    }
+  
+    register_dissector("ssl", dissect_ssl, proto_ssl);
+
 }
 
 /* If this dissector uses sub-dissector registration add a registration
@@ -2506,5 +2819,11 @@ proto_register_ssl(void)
 void
 proto_reg_handoff_ssl(void)
 {
-    dissector_add("tcp.port", TCP_PORT_SSL, dissect_ssl, proto_ssl);
+    dissector_handle_t ssl_handle;
+
+    ssl_handle = find_dissector("ssl");
+    dissector_add("tcp.port", TCP_PORT_SSL, ssl_handle);
+    dissector_add("tcp.port", TCP_PORT_SSL_LDAP, ssl_handle);
+    dissector_add("tcp.port", TCP_PORT_SSL_IMAP, ssl_handle);
+    dissector_add("tcp.port", TCP_PORT_SSL_POP, ssl_handle);
 }