more epan/dissectors/packet-xml.c
authorStefan Metzmacher <metze@samba.org>
Wed, 18 Oct 2017 16:35:56 +0000 (18:35 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 17 Oct 2018 14:09:07 +0000 (16:09 +0200)
Change-Id: Ib4e027d79406ed7ac6cdcefb89cc252ad322b0c8

epan/dissectors/packet-xml.c
epan/dissectors/packet-xml.h

index 746f8e86175d3d5947ce0f88cb4ea2ec890288e8..c6310ebe7903ac5b97aa3d42ae60d82778a5ee21 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <string.h>
 #include <errno.h>
+#include <stdio.h>
 
 #include <epan/packet.h>
 #include <epan/tvbparse.h>
 #include <epan/prefs.h>
 #include <epan/expert.h>
 #include <epan/garrayfix.h>
+#include <epan/asn1.h>
 #include <wsutil/str_util.h>
 #include <wsutil/report_message.h>
+#include <wsutil/wsgcrypt.h>
+#include "packet-kerberos.h"
+#include "read_keytab_file.h"
 
 #include "packet-xml.h"
 
@@ -249,6 +254,8 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
     current_frame->start_offset = 0;
     current_frame->length = tvb_captured_length(tvb);
 
+    current_frame->decryption_keys = wmem_map_new(wmem_packet_scope(), g_str_hash, g_str_equal);
+
     root_ns = NULL;
 
     if (pinfo->match_string)
@@ -359,7 +366,7 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
     int          hfid;
     gboolean     is_cdata      = FALSE;
     proto_item  *pi;
-    xml_frame_t *new_frame;
+    xml_frame_t *new_frame     = NULL;
     gchar       *text          = NULL;
 
     if (tok->id == XML_CDATA) {
@@ -373,13 +380,10 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
 
     pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, ENC_UTF_8|ENC_NA);
 
-
     text = tvb_format_text(tok->tvb, tok->offset, tok->len);
     proto_item_set_text(pi, "%s", text);
 
     if (is_cdata) {
-        xml_frame_t *value_type   = NULL;
-
         new_frame                 = wmem_new(wmem_packet_scope(), xml_frame_t);
         new_frame->type           = XML_FRAME_CDATA;
         new_frame->name           = NULL;
@@ -393,6 +397,12 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         new_frame->length         = tok->len;
         new_frame->ns             = NULL;
         new_frame->pinfo          = current_frame->pinfo;
+    }
+
+    if (new_frame != NULL &&
+        strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0)
+    {
+        xml_frame_t *value_type   = NULL;
 
         value_type = xml_get_attrib(current_frame, "ValueType");
         if (value_type != NULL) {
@@ -408,6 +418,50 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
             }
         }
     }
+
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+#if 0
+#ifdef HAVE_KERBEROS
+                if (!pinfo->fd->flags.visited && si->status == 0) {
+               enc_key_t *ek;
+
+               if (krb_decrypt) {
+                       read_keytab_file_from_preferences();
+               }
+
+               for (ek=enc_key_list;ek;ek=ek->next) {
+                       if (ek->fd_num == (int)pinfo->num) {
+                               break;
+                       }
+               }
+
+               if (ek != NULL) {
+                       smb2_sesid_info_t *sesid;
+                       guint8 custom_seskey[NTLMSSP_KEY_LEN] = { 0, };
+                       const guint8 *session_key;
+
+                       sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
+                       sesid->sesid = si->sesid;
+                       /* TODO: fill in the correct information */
+                       sesid->acct_name = NULL;
+                       sesid->domain_name = NULL;
+                       sesid->host_name = NULL;
+
+                       if (seskey_find_sid_key(si->sesid, custom_seskey)) {
+                               session_key = custom_seskey;
+                       } else {
+                               session_key = ek->keyvalue;
+                       }
+                       smb2_set_session_keys(sesid, session_key);
+                       sesid->server_port = pinfo->srcport;
+                       sesid->auth_frame = pinfo->num;
+                       sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+                       g_hash_table_insert(si->conv->sesids, sesid, sesid);
+               }
+       }
+#endif
+#endif
 }
 
 static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -455,6 +509,8 @@ static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbpa
 
     g_ptr_array_add(stack, new_frame);
 
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -470,6 +526,14 @@ static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_xmpli_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
 }
 
 static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -545,6 +609,8 @@ static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbpars
 
     g_ptr_array_add(stack, new_frame);
 
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_open_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
@@ -553,6 +619,8 @@ static void after_open_tag(void *tvbparse_data, const void *wanted_data _U_, tvb
     xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
 
     proto_item_append_text(current_frame->last_item, ">");
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -568,12 +636,40 @@ static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U_, t
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
                               tok->tvb, tok->offset, tok->len);
     }
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+}
+
+struct decryption_key {
+        gchar *id;
+        size_t key_length;
+        guint8 key[HASH_SHA1_LENGTH];
+};
+
+static void P_SHA1(const guint8 *Secret, guint32 Secret_len,
+                   const guint8 *Seed, guint32 Seed_len,
+                   guint8 Result[HASH_SHA1_LENGTH])
+{
+    gcry_md_hd_t  hd     = NULL;
+    guint8       *digest = NULL;
+
+    /*
+     * https://social.microsoft.com/Forums/en-US/c485d98b-6e0b-49e7-ab34-8ecf8d694d31/signing-soap-message-request-via-adfs?forum=crmdevelopment#6cee9fa8-dc24-4524-a5a2-c3d17e05d50e
+     */
+    gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, Secret, Secret_len);
+    gcry_md_write(hd, Seed, Seed_len);
+    digest = gcry_md_read(hd, GCRY_MD_SHA1);
+    memcpy(Result, digest, HASH_SHA1_LENGTH);
+
+    gcry_md_close(hd);
 }
 
 static void after_untag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
 {
     GPtrArray   *stack         = (GPtrArray *)tvbparse_data;
     xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
+    xml_frame_t *top_frame = (xml_frame_t *)g_ptr_array_index(stack, 0);
 
     proto_item_set_len(current_frame->item, (tok->offset - current_frame->start_offset) + tok->len);
     current_frame->length = (tok->offset - current_frame->start_offset) + tok->len;
@@ -586,6 +682,147 @@ static void after_untag(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+
+    if (current_frame->name_orig_case == NULL) {
+        return;
+    }
+
+#ifdef HAVE_KERBEROS
+    if (strcmp(current_frame->name_orig_case, "DerivedKeyToken") == 0) {
+        xml_frame_t *id_frame = xml_get_attrib(current_frame, "u:Id");
+        xml_frame_t *nonce_frame = xml_get_tag(current_frame, "Nonce");
+        xml_frame_t *nonce_cdata = NULL;
+        tvbuff_t *nonce_tvb = NULL;
+        enc_key_t *ek = NULL;
+        guint8 seed[64];
+        size_t seed_length = 16; // TODO
+        const size_t key_length = 16; //TODO
+
+        printf("%s:%s:%u: DerivedKeyToken->Id[%p]\n", __FILE__, G_STRFUNC, __LINE__, id_frame);
+        printf("%s:%s:%u: DerivedKeyToken->Nonce[%p]\n", __FILE__, G_STRFUNC, __LINE__, nonce_frame);
+    fflush(stdout);
+        if (id_frame != NULL && nonce_frame != NULL) {
+            nonce_cdata = xml_get_cdata(nonce_frame);
+        }
+        if (nonce_cdata != NULL) {
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+            gchar *text = tvb_format_text(nonce_cdata->value, 0,
+                                          tvb_reported_length(nonce_cdata->value));
+            nonce_tvb = base64_to_tvb(nonce_cdata->value, text);
+        }
+        if (nonce_tvb != NULL) {
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+
+            seed_length = tvb_reported_length(nonce_tvb);
+            seed_length = MIN(seed_length, sizeof(seed));
+            tvb_memcpy(nonce_tvb, seed, 0, seed_length);
+
+            if (krb_decrypt) {
+                read_keytab_file_from_preferences();
+            }
+
+            for (ek=enc_key_list;ek;ek=ek->next) {
+                if (ek->fd_num == (int)current_frame->pinfo->num) {
+                    break;
+                }
+            }
+        }
+    printf("%s:%s:%u: ek[%p]\n", __FILE__, G_STRFUNC, __LINE__, ek);
+    fflush(stdout);
+        if (ek != NULL) {
+            struct decryption_key *key;
+
+            key = wmem_new0(wmem_packet_scope(), struct decryption_key);
+            key->id = tvb_format_text(id_frame->value, 0, tvb_reported_length(id_frame->value));
+           P_SHA1(ek->keyvalue, ek->keylength, seed, seed_length, key->key);
+            key->key_length = key_length;
+
+           wmem_map_insert(top_frame->decryption_keys, key->id, key);
+    printf("%s:%s:%u: key_id[%s] (%02x%02x%02x%02x...)\n", __FILE__, G_STRFUNC, __LINE__, key->id,
+                                    key->key[0] & 0xFF, key->key[1] & 0xFF,
+                                    key->key[2] & 0xFF, key->key[3] & 0xFF);
+    fflush(stdout);
+        }
+        //proto_item_append_text(current_frame->last_item, "(ek[%p])", ek);
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+    }
+    if (strcmp(current_frame->name_orig_case, "CipherValue") == 0) {
+        xml_frame_t *encrypted_frame = current_frame->parent->parent;
+
+        printf("%s:%s:%u: CipherValue->Parent->Parent[%p]\n", __FILE__, G_STRFUNC, __LINE__,
+                encrypted_frame);
+        printf("%s:%s:%u: CipherValue->Parent->Parent[%s]\n", __FILE__, G_STRFUNC, __LINE__,
+                encrypted_frame->name_orig_case);
+    fflush(stdout);
+    }
+#endif
+#if 0
+        metze
+        strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0)
+        xml_frame_t *value_type   = NULL;
+
+        value_type = xml_get_attrib(current_frame, "ValueType");
+        if (value_type != NULL) {
+            const gchar *s = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
+            size_t l = strlen(s);
+            gint c;
+            c = tvb_strneql(value_type->value, 0, s, l);
+            if (c == 0) {
+                tvbuff_t *ssp_tvb = base64_to_tvb(new_frame->value, text);
+                add_new_data_source(current_frame->pinfo, ssp_tvb, "GSSAPI Data");
+                call_dissector(gssapi_handle, ssp_tvb,
+                               current_frame->pinfo, current_frame->tree);
+            }
+        }
+    }
+
+#ifdef HAVE_KERBEROS
+                if (!pinfo->fd->flags.visited && si->status == 0) {
+               enc_key_t *ek;
+
+               if (krb_decrypt) {
+                       read_keytab_file_from_preferences();
+               }
+
+               for (ek=enc_key_list;ek;ek=ek->next) {
+                       if (ek->fd_num == (int)pinfo->num) {
+                               break;
+                       }
+               }
+
+               if (ek != NULL) {
+                       smb2_sesid_info_t *sesid;
+                       guint8 custom_seskey[NTLMSSP_KEY_LEN] = { 0, };
+                       const guint8 *session_key;
+
+                       sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
+                       sesid->sesid = si->sesid;
+                       /* TODO: fill in the correct information */
+                       sesid->acct_name = NULL;
+                       sesid->domain_name = NULL;
+                       sesid->host_name = NULL;
+
+                       if (seskey_find_sid_key(si->sesid, custom_seskey)) {
+                               session_key = custom_seskey;
+                       } else {
+                               session_key = ek->keyvalue;
+                       }
+                       smb2_set_session_keys(sesid, session_key);
+                       sesid->server_port = pinfo->srcport;
+                       sesid->auth_frame = pinfo->num;
+                       sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+                       g_hash_table_insert(si->conv->sesids, sesid, sesid);
+               }
+       }
+#endif
+#endif
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -617,6 +854,8 @@ static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_,
     new_frame->pinfo          = current_frame->pinfo;
 
     g_ptr_array_add(stack, new_frame);
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void pop_stack(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
@@ -630,6 +869,8 @@ static void pop_stack(void *tvbparse_data, const void *wanted_data _U_, tvbparse
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -644,6 +885,8 @@ static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U_, tv
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void get_attrib_value(void *tvbparse_data _U_, const void *wanted_data _U_, tvbparse_elem_t *tok)
index 792da88013a3cf9a7613bd7e6dabded627e9f175..c412b7582d72a324899840b6263afc4cd6c00bc5 100644 (file)
@@ -66,6 +66,7 @@ typedef struct _xml_frame_t {
     int start_offset;
     int length;
     packet_info* pinfo;
+    wmem_map_t *decryption_keys;
 } xml_frame_t;
 
 WS_DLL_PUBLIC