[PATCH] ndrdump: Add the option --hex-input for hexdump parsing

Cody Harrington cody at harringtonca.com
Sun Oct 9 10:22:52 UTC 2016


Hi all,

I wrote a patch for ndrdump that adds the option --hex-input, which 
allows you to pass in a hexdump instead of a binary output for 
debugging. This feature was originally suggested to me by Andrew Bartlett.

Please find the patch attached. The code was developed against the 
master branch of the Github repository at the end of August. I've tested 
merging the most recent version of master with these changes just now, 
and there seem to be no conflicts.

This is my first time contributing, so a review and any feedback would 
be greatly appreciated :^)

Regards,

Cody Harrington
-------------- next part --------------
From 996869094d9af28e704e3bb3e10343431ac6ad68 Mon Sep 17 00:00:00 2001
From: Cody Harrington <cody at harringtonca.com>
Date: Sun, 28 Aug 2016 03:01:18 +1200
Subject: [PATCH] ndrdump: Add the option --hex-input for hexdump parsing

This allows the user to input a hexdump that has been generated by the dump option.

Signed-off-by: Cody Harrington <cody at harringtonca.com>
---
 lib/util/samba_util.h  | 13 +++++++++----
 lib/util/util.c        | 44 ++++++++++++++++++++++++++++++++++++++++++--
 librpc/tools/ndrdump.c | 22 +++++++++++++++-------
 3 files changed, 66 insertions(+), 13 deletions(-)

diff --git a/lib/util/samba_util.h b/lib/util/samba_util.h
index c339161..388fff2 100644
--- a/lib/util/samba_util.h
+++ b/lib/util/samba_util.h
@@ -128,7 +128,7 @@ _PUBLIC_ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len);
  * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,
  */
 _PUBLIC_ char** generate_unique_strs(TALLOC_CTX *mem_ctx, size_t len,
-                                         uint32_t num);
+					 uint32_t num);
 
 /* The following definitions come from lib/util/dprintf.c  */
 
@@ -182,6 +182,11 @@ _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t
 _PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) ;
 
 /**
+ * Parse a hex dump and return a data blob
+ */
+_PUBLIC_ _PURE_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t len);
+
+/**
  * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
  */
 _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen);
@@ -597,7 +602,7 @@ _PUBLIC_ void daemon_status(const char *name, const char *msg);
  * @param[in]  prompt   The prompt to show to ask for the password.
  *
  * @param[out] buf    The buffer the password should be stored. It NEEDS to be
- *                      empty or filled out.
+ *		      empty or filled out.
  *
  * @param[in]  len      The length of the buffer.
  *
@@ -614,8 +619,8 @@ _PUBLIC_ int samba_getpass(const char *prompt, char *buf, size_t len,
  * Load a ini-style file.
  */
 bool pm_process( const char *fileName,
-                 bool (*sfunc)(const char *, void *),
-                 bool (*pfunc)(const char *, const char *, void *),
+		 bool (*sfunc)(const char *, void *),
+		 bool (*pfunc)(const char *, const char *, void *),
 				 void *userdata);
 
 void print_asc(int level, const uint8_t *buf,int len);
diff --git a/lib/util/util.c b/lib/util/util.c
index a8bbc15..4623493 100644
--- a/lib/util/util.c
+++ b/lib/util/util.c
@@ -903,8 +903,8 @@ _PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t
 	return num_chars;
 }
 
-/** 
- * Parse a hex string and return a data blob. 
+/**
+ * Parse a hex string and return a data blob.
  */
 _PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) 
 {
@@ -918,6 +918,46 @@ _PUBLIC_ _PURE_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *s
 }
 
 /**
+ * Parse a hex dump and return a data blob. Hex dump is structured as 
+ * is generated from dump_data_cb() elsewhere in this file
+ * 
+ */
+_PUBLIC_ _PURE_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t hexdump_len)
+{
+	DATA_BLOB ret_blob = {'\0'};
+	size_t i = 0;
+	size_t char_count = 0;
+	/* hexdump line length is 77 chars long. We then use the ASCII representation of the bytes
+	 * at the end of the final line to calculate how many are in that line, minus the extra space
+	 * and newline. */
+	size_t hexdump_byte_count = (16 * (hexdump_len / 77));
+	if (hexdump_len % 77) {
+		hexdump_byte_count += ((hexdump_len % 77) - 59 - 2);
+	}
+	
+	ret_blob = data_blob_talloc(mem_ctx, NULL, hexdump_byte_count+1);
+	for (; i+1 < hexdump_len && hexdump[i] != 0 && hexdump[i+1] != 0; i++) {
+		if ((i%77) == 0) 
+			i += 7; /* Skip the offset at the start of the line */
+		if ((i%77) < 56) { /* position 56 is after both hex chunks */
+			if (hexdump[i] != ' ') {
+				char_count += strhex_to_str((char *)&ret_blob.data[char_count],
+							    hexdump_byte_count - char_count,
+							    &hexdump[i], 2);
+				i += 2;
+			} else {
+				i++;
+			}
+		} else {
+			i++;
+		}
+	}
+	ret_blob.length = char_count;
+	
+	return ret_blob;
+}
+
+/**
  * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
  */
 _PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
diff --git a/librpc/tools/ndrdump.c b/librpc/tools/ndrdump.c
index d534e3c..b1e96b8 100644
--- a/librpc/tools/ndrdump.c
+++ b/librpc/tools/ndrdump.c
@@ -213,8 +213,9 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 	bool dumpdata = false;
 	bool assume_ndr64 = false;
 	bool quiet = false;
+	bool hex_input = false;
 	int opt;
-	enum {OPT_CONTEXT_FILE=1000, OPT_VALIDATE, OPT_DUMP_DATA, OPT_LOAD_DSO, OPT_NDR64, OPT_QUIET};
+	enum {OPT_CONTEXT_FILE=1000, OPT_VALIDATE, OPT_DUMP_DATA, OPT_LOAD_DSO, OPT_NDR64, OPT_QUIET, OPT_HEX_INPUT};
 	struct poptOption long_options[] = {
 		POPT_AUTOHELP
 		{"context-file", 'c', POPT_ARG_STRING, NULL, OPT_CONTEXT_FILE, "In-filename to parse first", "CTX-FILE" },
@@ -223,6 +224,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 		{"load-dso", 'l', POPT_ARG_STRING, NULL, OPT_LOAD_DSO, "load from shared object file", NULL },
 		{"ndr64", 0, POPT_ARG_NONE, NULL, OPT_NDR64, "Assume NDR64 data", NULL },
 		{"quiet", 0, POPT_ARG_NONE, NULL, OPT_QUIET, "Don't actually dump anything", NULL },
+		{"hex-input", 0, POPT_ARG_NONE, NULL, OPT_HEX_INPUT, "Read the input file in as a hex dump", NULL },
 		POPT_COMMON_SAMBA
 		POPT_COMMON_VERSION
 		{ NULL }
@@ -231,7 +233,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 	const struct ndr_interface_call_pipes *out_pipes = NULL;
 	uint32_t highest_ofs;
 	struct dcerpc_sec_verification_trailer *sec_vt = NULL;
-
+	
 	ndr_table_init();
 
 	/* Initialise samba stuff */
@@ -266,6 +268,9 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 		case OPT_QUIET:
 			quiet = true;
 			break;
+		case OPT_HEX_INPUT:
+			hex_input = true;
+			break;
 		}
 	}
 
@@ -381,7 +386,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 			exit(1);
 		}
 		memcpy(v_st, st, f->struct_size);
-	} 
+	}
 
 	if (filename)
 		data = (uint8_t *)file_load(filename, &size, 0, mem_ctx);
@@ -395,9 +400,13 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 			perror("stdin");
 		exit(1);
 	}
-
-	blob.data = data;
-	blob.length = size;
+	
+	if (hex_input) {
+		blob = hexdump_to_data_blob(mem_ctx, (char *)data, size);
+	} else {
+		blob.data = data;
+		blob.length = size;
+	}
 
 	ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
 	if (ndr_pull == NULL) {
@@ -584,7 +593,6 @@ static void ndr_print_dummy(struct ndr_print *ndr, const char *format, ...)
 	}
 
 	printf("dump OK\n");
-
 	talloc_free(mem_ctx);
 
 	poptFreeContext(pc);
-- 
2.9.3



More information about the samba-technical mailing list