#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"
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)
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) {
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;
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) {
}
}
}
+
+ //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)
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)
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)
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_)
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)
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;
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)
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_)
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)
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)