epan/dissectors/packet-xml.c no printf
[metze/wireshark/wip.git] / epan / dissectors / packet-xml.c
index 746f8e86175d3d5947ce0f88cb4ea2ec890288e8..4961f7a47f390ff98a98ae582d38c01f41ddd07f 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,215 @@ 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 = wmem_strdup_printf(wmem_packet_scope(), "#%s",
+                                         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;
+        xml_frame_t *key_info_frame = NULL;
+        xml_frame_t *token_frame = NULL;
+        xml_frame_t *reference_frame = NULL;
+        xml_frame_t *uri_frame = NULL;
+        const struct decryption_key *key = NULL;
+        xml_frame_t *cdata_frame = NULL;
+        tvbuff_t *crypt_tvb = NULL;
+        tvbuff_t *plain_tvb = NULL;
+
+  //      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);
+
+        key_info_frame = xml_get_tag(encrypted_frame, "KeyInfo");
+        if (key_info_frame != NULL) {
+            token_frame = xml_get_tag(key_info_frame, "SecurityTokenReference");
+        }
+        if (token_frame != NULL) {
+            reference_frame = xml_get_tag(token_frame, "Reference");
+        }
+        if (reference_frame != NULL) {
+            uri_frame = xml_get_attrib(reference_frame, "URI");
+        }
+
+        //printf("%s:%s:%u: key_info[%p] token[%p] reference[%p] uri[%p]\n", __FILE__, G_STRFUNC, __LINE__,
+        //       key_info_frame, token_frame, reference_frame, uri_frame);
+    fflush(stdout);
+        if (uri_frame != NULL) {
+            gchar *key_id = tvb_format_text(uri_frame->value, 0,
+                                            tvb_reported_length(uri_frame->value));
+
+
+        //printf("%s:%s:%u: URI[%s]\n", __FILE__, G_STRFUNC, __LINE__, key_id);
+    fflush(stdout);
+           key = (const struct decryption_key *)wmem_map_lookup(top_frame->decryption_keys, key_id);
+        }
+        if (key != NULL) {
+//    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);
+            cdata_frame = xml_get_cdata(current_frame);
+        }
+        if (cdata_frame != NULL) {
+            gchar *text = tvb_format_text(cdata_frame->value, 0,
+                                          tvb_reported_length(cdata_frame->value));
+            crypt_tvb = base64_to_tvb(cdata_frame->value, text);
+        }
+        if (crypt_tvb != NULL) {
+               gcry_cipher_hd_t cipher_hd = NULL;
+                guint8 *data = NULL;
+                size_t data_length = tvb_reported_length(crypt_tvb);
+
+//    printf("%s:%s:%u: data_length[%zu]\n", __FILE__, G_STRFUNC, __LINE__, data_length);
+    fflush(stdout);
+               data = (guint8 *)tvb_memdup(wmem_packet_scope(),
+                                            crypt_tvb, 0, data_length);
+
+               /* Open the cipher. */
+               gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
+
+               gcry_cipher_setkey(cipher_hd, key->key, key->key_length);
+               //gcry_cipher_setctr(cipher_hd, A_1, NTLMSSP_KEY_LEN);
+               //gcry_cipher_encrypt(cipher_hd, plain_data, sti->size, NULL, 0);
+               //gcry_cipher_decrypt(cipher_hd, data, data_length, NULL, 0);
+               gcry_cipher_encrypt(cipher_hd, data, data_length, NULL, 0);
+               gcry_cipher_close(cipher_hd);
+
+               plain_tvb = tvb_new_child_real_data(crypt_tvb, data,
+                                                    data_length, data_length);
+                add_new_data_source(current_frame->pinfo, plain_tvb, "Decrypted Data");
+        }
+    }
+#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 +922,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 +937,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 +953,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)