The branch, master has been updated
       via  f7f92803f60 librpc: Check for NULL pointer in value() in 
ntlmssp_AUTHENTICATE
       via  33e9021cbee selftest: Test repushing an ntlmssp AUTHENTICATE_MESSAGE
       via  ac1be895d25 selftest: Confirm that NDR bugs are fixed in DCOM code
       via  1aec7425752 pidl: check the size of pulled arrays of arrays
       via  536a84935ce ndr_orpc: properly allocate empty DUALSTRINGARRAY
       via  b1eda993b65 selftest: Confirm that --base64-input and --input work 
and a PIDL bug is fixed.
       via  24fa3374e04 python: Return the stdout when also checking error codes
       via  2da54d11f1e ndrdump: Still print --dump bytes after parse failure
       via  0491f172751 ndrdump: Invert sense of --stop-on-parse-failure into 
--print-after-parse-failure
       via  c83ad13e589 ndrdump: Return a different error code for ndr_pull() 
failures
       via  6f0d30fd5cc ndrdump: Allow for base64-encoded input in a file and 
on the command line
       via  d4eabfb763b ndrdump: Check for input decode failures
       via  3194baaf88d ndrdump: Add const
       via  c90bc75df84 ndrdump: TALLOC_FREE() on each exit path to allow 
running with leak detection
       via  8a6f1de67b1 ndrdump: print structure name when failing to setup
       via  db6c12f1584 ndrdump: Fix one more NTSTATUS rather than friendly ndr 
message
      from  1af1ebe54ae librpc: Unify packet dumping on ndr_pull() failure

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit f7f92803f600f8d302cdbb668c42ca8b186a797f
Author: Andrew Bartlett <[email protected]>
Date:   Tue Nov 19 17:38:50 2019 +1300

    librpc: Check for NULL pointer in value() in ntlmssp_AUTHENTICATE
    
    This allows ndrdump --validate to avoid following a NULL pointer when 
re-pushing
    a valid but unusual input.
    
    It also avoids an issue if the Samba server code were to provide a response
    without an EncryptedRandomSessionKey.
    
    At this stage ntlmssp.idl is not used for this, instead the packets are
    generated with msrpc_gen().
    
    Found by Douglas Bagnall using Hongfuzz and the new fuzz_ndr_X
    fuzzer.
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>
    
    Autobuild-User(master): Andrew Bartlett <[email protected]>
    Autobuild-Date(master): Wed Nov 20 06:06:29 UTC 2019 on sn-devel-184

commit 33e9021cbee4c17ee2f11d02b99902a742d77293
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 12:14:52 2019 +1300

    selftest: Test repushing an ntlmssp AUTHENTICATE_MESSAGE
    
    This demonstrates a bug found by Douglas Bagnall using Hongfuzz and the new 
fuzz_ndr_X
    fuzzer where the value() evaluatuion could segfault if it was made to 
follow a NULL
    pointer.
    
    This also demonstrates that the --base64 mode works on file inputs.
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit ac1be895d2501dc79dcff2c1e03549fe5b5a930c
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 11:40:51 2019 +1300

    selftest: Confirm that NDR bugs are fixed in DCOM code
    
    Test input provided by Michael Hanselmann and found using Hongfuzz.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13875
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 1aec742575252d1efcc47a8e9023889bfb0e5709
Author: Douglas Bagnall <[email protected]>
Date:   Thu Oct 31 09:35:19 2019 +1300

    pidl: check the size of pulled arrays of arrays
    
    We were accidentally checking the memory just past the array instead of
    checking each member.
    
    This could have led to the size of some arrays not being checked.
    
    Found by Michael Hanselmann using Honggfuzz and an fuzzer for Samba's
    NDR layer.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13877
    
    Signed-off-by: Douglas Bagnall <[email protected]>
    Pair-programmed-with: Andrew Bartlett <[email protected]>
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Andrew Bartlett <[email protected]>

commit 536a84935ce7647f43528d6d376f6762c5e8eb78
Author: Douglas Bagnall <[email protected]>
Date:   Wed Oct 30 15:02:49 2019 +1300

    ndr_orpc: properly allocate empty DUALSTRINGARRAY
    
    When there is no data we still need to allocate for the terminating NULL.
    
    Found by Michael Hanselmann using Honggfuzz and an fuzzer for Samba's
    NDR layer.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13875
    
    Signed-off-by: Douglas Bagnall <[email protected]>
    Reviewed-by: Andrew Bartlett <[email protected]>

commit b1eda993b658590ebb0a8225e448ce399946ed83
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 10:56:14 2019 +1300

    selftest: Confirm that --base64-input and --input work and a PIDL bug is 
fixed.
    
    The PIDL bug is in the handling of arrays of arrays.
    
    Test input provided by Michael Hanselmann and found using Hongfuzz.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13875
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 24fa3374e041f9ad26b6f124aed0c5a61a7d551e
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 10:55:18 2019 +1300

    python: Return the stdout when also checking error codes
    
    This will aid in checking that ndrdump behaves as expected when
    failing to parse
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 2da54d11f1e9744885558a64e72bf93b6009ae0e
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 10:45:02 2019 +1300

    ndrdump: Still print --dump bytes after parse failure
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 0491f1727513137a5cf86073d11608b7dd8a2056
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 13:26:11 2019 +1300

    ndrdump: Invert sense of --stop-on-parse-failure into 
--print-after-parse-failure
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit c83ad13e5893889852cbd7d2208bf45c2b72b07c
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 10:39:54 2019 +1300

    ndrdump: Return a different error code for ndr_pull() failures
    
    This may assist in distinguishing between "runner" and "pull" failures.
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 6f0d30fd5cc921dedbc0f0741e3959b4ebc4027d
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 10:00:52 2019 +1300

    ndrdump: Allow for base64-encoded input in a file and on the command line
    
    It has become customary to provide reproduction steps for fuzzing failures
    in terms of an ndrdump command line.  This allows the input to be provided
    as a argument or in a file rather than via base64 -d.  This makes 
reproducing
    the issue easier as everything can be put in a plaintext bug report.
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit d4eabfb763b7c0ea6b112ea3a129977a68466977
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 09:59:07 2019 +1300

    ndrdump: Check for input decode failures
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 3194baaf88d78f86cbf821600cd69712e1cc02a2
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 09:58:15 2019 +1300

    ndrdump: Add const
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit c90bc75df8446c79a9e251c7b07a59674d828505
Author: Andrew Bartlett <[email protected]>
Date:   Mon Nov 18 13:46:53 2019 +1300

    ndrdump: TALLOC_FREE() on each exit path to allow running with leak 
detection
    
    This allows us to learn if there are other memory leaks not on the mem_ctx
    during the processing of the packet.
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit 8a6f1de67b1c2e925cce8fb20b6657a425cbaedb
Author: Andrew Bartlett <[email protected]>
Date:   Mon Nov 18 13:44:02 2019 +1300

    ndrdump: print structure name when failing to setup
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

commit db6c12f1584215c21cd5e56bef13c6d1c8b608ce
Author: Andrew Bartlett <[email protected]>
Date:   Wed Nov 20 12:17:37 2019 +1300

    ndrdump: Fix one more NTSTATUS rather than friendly ndr message
    
    Signed-off-by: Andrew Bartlett <[email protected]>
    Reviewed-by: Douglas Bagnall <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 librpc/idl/ntlmssp.idl                             |   2 +-
 librpc/ndr/ndr_orpc.c                              |   4 +-
 librpc/tools/ndrdump.c                             | 120 +++++++++++++-----
 pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm           |   4 +
 python/samba/tests/__init__.py                     |   1 +
 python/samba/tests/blackbox/ndrdump.py             | 100 +++++++++++++++
 .../fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt    |   1 +
 .../tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt  | 134 +++++++++++++++++++++
 8 files changed, 332 insertions(+), 34 deletions(-)
 create mode 100644 
source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt
 create mode 100644 source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt


Changeset truncated at 500 lines:

diff --git a/librpc/idl/ntlmssp.idl b/librpc/idl/ntlmssp.idl
index f984b7b0b4c..dd4c0b91640 100644
--- a/librpc/idl/ntlmssp.idl
+++ b/librpc/idl/ntlmssp.idl
@@ -271,7 +271,7 @@ interface ntlmssp
                [value(ndr_ntlmssp_string_length(NegotiateFlags, Workstation))] 
uint16 WorkstationLen;
                [value(WorkstationLen)] uint16 WorkstationMaxLen;
                [relative] [subcontext(0),subcontext_size(WorkstationLen)] 
[flag(ndr_ntlmssp_negotiated_string_flags(r->NegotiateFlags))] string 
*Workstation;
-               [value(EncryptedRandomSessionKey->length)] uint16 
EncryptedRandomSessionKeyLen;
+               [value(EncryptedRandomSessionKey == NULL ? 0 : 
EncryptedRandomSessionKey->length)] uint16 EncryptedRandomSessionKeyLen;
                [value(EncryptedRandomSessionKeyLen)] uint16 
EncryptedRandomSessionKeyMaxLen;
                [relative] 
[subcontext(0),subcontext_size(EncryptedRandomSessionKeyLen)] DATA_BLOB 
*EncryptedRandomSessionKey;
                NEGOTIATE NegotiateFlags;
diff --git a/librpc/ndr/ndr_orpc.c b/librpc/ndr/ndr_orpc.c
index f24ddc5f826..01ba885d942 100644
--- a/librpc/ndr/ndr_orpc.c
+++ b/librpc/ndr/ndr_orpc.c
@@ -37,7 +37,7 @@ enum ndr_err_code ndr_pull_DUALSTRINGARRAY(struct ndr_pull 
*ndr, int ndr_flags,
        NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &num_entries));
        NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &security_offset));
 
-       ar->stringbindings = talloc_array(ndr, struct STRINGBINDING *, 
num_entries);
+       ar->stringbindings = talloc_array(ndr, struct STRINGBINDING *, 1);
        ar->stringbindings[0] = NULL;
 
        do {
@@ -56,7 +56,7 @@ enum ndr_err_code ndr_pull_DUALSTRINGARRAY(struct ndr_pull 
*ndr, int ndr_flags,
        ar->stringbindings[towernum] = NULL;
        towernum = 0;
 
-       ar->securitybindings = talloc_array(ndr, struct SECURITYBINDING *, 
num_entries);
+       ar->securitybindings = talloc_array(ndr, struct SECURITYBINDING *, 1);
        ar->securitybindings[0] = NULL;
 
        do {
diff --git a/librpc/tools/ndrdump.c b/librpc/tools/ndrdump.c
index e911cf4c1e4..f02b1edab02 100644
--- a/librpc/tools/ndrdump.c
+++ b/librpc/tools/ndrdump.c
@@ -26,6 +26,7 @@
 #include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "lib/cmdline/popt_common.h"
 #include "param/param.h"
+#include "lib/util/base64.h"
 
 static const struct ndr_interface_call *find_function(
        const struct ndr_interface_table *p,
@@ -265,7 +266,8 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
         * name of a public structure
         */
        const char *format = NULL;
-       uint8_t *data;
+       const char *cmdline_input = NULL;
+       const uint8_t *data;
        size_t size;
        DATA_BLOB blob;
        struct ndr_pull *ndr_pull;
@@ -284,7 +286,8 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
        bool assume_ndr64 = false;
        bool quiet = false;
        bool hex_input = false;
-       bool stop_on_parse_failure = false;
+       bool base64_input = false;
+       bool print_after_parse_failure = false;
        int opt;
        enum {
                OPT_CONTEXT_FILE=1000,
@@ -293,8 +296,10 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                OPT_LOAD_DSO,
                OPT_NDR64,
                OPT_QUIET,
+               OPT_BASE64_INPUT,
                OPT_HEX_INPUT,
-               OPT_STOP_ON_PARSE_FAILURE,
+               OPT_CMDLINE_INPUT,
+               OPT_PRINT_AFTER_PARSE_FAILURE,
        };
        struct poptOption long_options[] = {
                POPT_AUTOHELP
@@ -304,9 +309,11 @@ 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 },
+               {"base64-input", 0, POPT_ARG_NONE, NULL, OPT_BASE64_INPUT, 
"Read the input file in as a base64 string", NULL },
                {"hex-input", 0, POPT_ARG_NONE, NULL, OPT_HEX_INPUT, "Read the 
input file in as a hex dump", NULL },
-               {"stop-on-parse-failure", 0, POPT_ARG_NONE, NULL, 
OPT_STOP_ON_PARSE_FAILURE,
-                "Do not try to print structures that fail to parse.", NULL },
+               {"input", 0, POPT_ARG_STRING, NULL, OPT_CMDLINE_INPUT, "Provide 
the input on the command line (use with --base64-input)", "INPUT" },
+               {"print-after-parse-failure", 0, POPT_ARG_NONE, NULL, 
OPT_PRINT_AFTER_PARSE_FAILURE,
+                "Try to print structures that fail to parse (used to develop 
parsers, segfaults are likely).", NULL },
                POPT_COMMON_SAMBA
                POPT_COMMON_VERSION
                { NULL }
@@ -348,11 +355,17 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                case OPT_QUIET:
                        quiet = true;
                        break;
+               case OPT_BASE64_INPUT:
+                       base64_input = true;
+                       break;
                case OPT_HEX_INPUT:
                        hex_input = true;
                        break;
-               case OPT_STOP_ON_PARSE_FAILURE:
-                       stop_on_parse_failure = true;
+               case OPT_CMDLINE_INPUT:
+                       cmdline_input = poptGetOptArg(pc);
+                       break;
+               case OPT_PRINT_AFTER_PARSE_FAILURE:
+                       print_after_parse_failure = true;
                        break;
                }
        }
@@ -419,34 +432,43 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
 
        st = talloc_zero_size(mem_ctx, f->struct_size);
        if (!st) {
-               printf("Unable to allocate %d bytes\n", (int)f->struct_size);
+               printf("Unable to allocate %d bytes for %s structure\n",
+                      (int)f->struct_size,
+                      f->name);
+               TALLOC_FREE(mem_ctx);
                exit(1);
        }
 
        v_st = talloc_zero_size(mem_ctx, f->struct_size);
        if (!v_st) {
-               printf("Unable to allocate %d bytes\n", (int)f->struct_size);
+               printf("Unable to allocate %d bytes for %s validation "
+                      "structure\n",
+                      (int)f->struct_size,
+                      f->name);
+               TALLOC_FREE(mem_ctx);
                exit(1);
        }
 
        if (ctx_filename) {
                if (flags & NDR_IN) {
                        printf("Context file can only be used for \"out\" 
packages\n");
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
                        
                data = (uint8_t *)file_load(ctx_filename, &size, 0, mem_ctx);
                if (!data) {
                        perror(ctx_filename);
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
 
-               blob.data = data;
-               blob.length = size;
+               blob = data_blob_const(data, size);
 
                ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
                if (ndr_pull == NULL) {
                        perror("ndr_pull_init_blob");
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
                ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
@@ -469,15 +491,24 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        printf("pull for context file returned %s\n",
                               ndr_map_error2string(ndr_err));
-                       exit(1);
+                       TALLOC_FREE(mem_ctx);
+                       exit(2);
                }
                memcpy(v_st, st, f->struct_size);
        }
 
-       if (filename)
+       if (filename && cmdline_input) {
+               printf("cannot combine --input with a filename\n");
+               TALLOC_FREE(mem_ctx);
+               exit(1);
+       } else if (cmdline_input) {
+               data = (const uint8_t *)cmdline_input;
+               size = strlen(cmdline_input);
+       } else if (filename) {
                data = (uint8_t *)file_load(filename, &size, 0, mem_ctx);
-       else
+       } else {
                data = (uint8_t *)stdin_load(mem_ctx, &size);
+       }
 
        if (!data) {
                if (filename)
@@ -487,16 +518,33 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                exit(1);
        }
        
-       if (hex_input) {
-               blob = hexdump_to_data_blob(mem_ctx, (char *)data, size);
+       if (hex_input && base64_input) {
+               printf("cannot combine --hex-input with --base64-input\n");
+               TALLOC_FREE(mem_ctx);
+               exit(1);
+
+       } else if (hex_input) {
+               blob = hexdump_to_data_blob(mem_ctx, (const char *)data, size);
+       } else if (base64_input) {
+               /* Use talloc_strndup() to ensure null termination */
+               blob = base64_decode_data_blob(talloc_strndup(mem_ctx,
+                                                             (const char 
*)data, size));
+               /* base64_decode_data_blob() allocates on NULL */
+               talloc_steal(mem_ctx, blob.data);
        } else {
-               blob.data = data;
-               blob.length = size;
+               blob = data_blob_const(data, size);
+       }
+
+       if (data != NULL && blob.data == NULL) {
+               printf("failed to decode input data\n");
+               TALLOC_FREE(mem_ctx);
+               exit(1);
        }
 
        ndr_pull = ndr_pull_init_blob(&blob, mem_ctx);
        if (ndr_pull == NULL) {
                perror("ndr_pull_init_blob");
+               TALLOC_FREE(mem_ctx);
                exit(1);
        }
        ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
@@ -536,8 +584,9 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                                                      ndr_print,
                                                      &f->out_pipes);
                if (!NT_STATUS_IS_OK(status)) {
-                       printf("dump FAILED\n");
-                       exit(1);
+                       printf("pull and dump of pipes FAILED\n");
+                       TALLOC_FREE(mem_ctx);
+                       exit(2);
                }
        }
 
@@ -545,17 +594,22 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
        printf("pull returned %s\n",
               ndr_map_error2string(ndr_err));
 
-       if (stop_on_parse_failure && !NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               printf("not printing because --stop-on-parse-failure\n");
-               exit(1);
-       }
-
        if (ndr_pull->offset > ndr_pull->relative_highest_offset) {
                highest_ofs = ndr_pull->offset;
        } else {
                highest_ofs = ndr_pull->relative_highest_offset;
        }
 
+       if (dumpdata) {
+               printf("%d bytes consumed\n", highest_ofs);
+               ndrdump_data(blob.data, blob.length, dumpdata);
+       }
+
+       if (!print_after_parse_failure && !NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               TALLOC_FREE(mem_ctx);
+               exit(2);
+       }
+
        if (highest_ofs != ndr_pull->data_size) {
                printf("WARNING! %d unread bytes\n", ndr_pull->data_size - 
highest_ofs);
                ndrdump_data(ndr_pull->data+highest_ofs,
@@ -563,9 +617,10 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                             dumpdata);
        }
 
-       if (dumpdata) {
-               printf("%d bytes consumed\n", highest_ofs);
-               ndrdump_data(blob.data, blob.length, dumpdata);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               printf("WARNING: pull of %s was incomplete, "
+                      "therefore the parse below may SEGFAULT\n",
+                       f->name);
        }
 
        f->ndr_print(ndr_print, format, flags, st);
@@ -602,10 +657,11 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                }
 
                ndr_err = f->ndr_push(ndr_v_push, flags, st);
-               status = ndr_map_error2ntstatus(ndr_err);
-               printf("push returned %s\n", nt_errstr(status));
+               printf("push returned %s\n",
+                      ndr_map_error2string(ndr_err));
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        printf("validate push FAILED\n");
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
 
@@ -619,6 +675,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                ndr_v_pull = ndr_pull_init_blob(&v_blob, mem_ctx);
                if (ndr_v_pull == NULL) {
                        perror("ndr_pull_init_blob");
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
                ndr_v_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
@@ -628,6 +685,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
                       ndr_map_error2string(ndr_err));
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        printf("validate pull FAILED\n");
+                       TALLOC_FREE(mem_ctx);
                        exit(1);
                }
 
@@ -689,7 +747,7 @@ static void ndr_print_dummy(struct ndr_print *ndr, const 
char *format, ...)
        }
 
        printf("dump OK\n");
-       talloc_free(mem_ctx);
+       TALLOC_FREE(mem_ctx);
 
        poptFreeContext(pc);
        
diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm 
b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
index 8759e46aedb..c1a2cc99cb7 100644
--- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
+++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
@@ -1247,10 +1247,14 @@ sub ParseElementPullLevel
 
                if ($deferred and ContainsDeferred($e, $l)) {
                        $self->pidl("for ($counter = 0; $counter < ($length); 
$counter++) {");
+                       $self->defer("for ($counter = 0; $counter < ($length); 
$counter++) {");
+                       $self->defer_indent;
                        $self->indent;
                        $self->ParseElementPullLevel($e,GetNextLevel($e,$l), 
$ndr, $var_name, $env, 0, 1);
                        $self->deindent;
+                       $self->defer_deindent;
                        $self->pidl("}");
+                       $self->defer("}");
                }
 
                $self->ParseMemCtxPullEnd($e, $l, $ndr);
diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py
index fef21d261ca..3f22eaa1c94 100644
--- a/python/samba/tests/__init__.py
+++ b/python/samba/tests/__init__.py
@@ -438,6 +438,7 @@ class BlackboxTestCase(TestCaseInTempDir):
                                        stdoutdata,
                                        stderrdata,
                                        msg)
+        return stdoutdata
 
     def check_output(self, line):
         use_shell = not isinstance(line, list)
diff --git a/python/samba/tests/blackbox/ndrdump.py 
b/python/samba/tests/blackbox/ndrdump.py
index 4e638c920d8..ca637b3ac7b 100644
--- a/python/samba/tests/blackbox/ndrdump.py
+++ b/python/samba/tests/blackbox/ndrdump.py
@@ -110,3 +110,103 @@ dump OK
         # check_output will return bytes
         # convert expected to bytes for python 3
         self.assertEqual(actual, expected.encode('utf-8'))
+
+    def test_ndrdump_fuzzed_clusapi_QueryAllValues(self):
+        expected = b'''pull returned Success
+WARNING! 53 unread bytes
+[0000] 00 FF 00 00 FF 00 00 00   00 09 00 00 00 08 00 33   ........ .......3
+[0010] 33 32 37 36 32 36 39 33   32 37 36 38 34 01 00 00   32762693 27684...
+[0020] 80 32 0D FF 00 00 FF 00   00 00 00 08 00 00 00 1C   .2...... ........
+[0030] F1 29 08 00 00                                     .)... ''' \
+        b'''
+    clusapi_QueryAllValues: struct clusapi_QueryAllValues
+        out: struct clusapi_QueryAllValues
+            pcbData                  : *
+                pcbData                  : 0x01000000 (16777216)
+            ppData                   : *
+                ppData: ARRAY(1)
+                    ppData                   : NULL
+            rpc_status               : *
+                rpc_status               : WERR_OK
+            result                   : WERR_NOT_ENOUGH_MEMORY
+dump OK
+'''
+        try:
+            actual = self.check_output(
+                'ndrdump clusapi clusapi_QueryAllValues out ' +\
+                '--base64-input --input=' +\
+                
'AAAAAQEAAAAAAAAAAAAAAAgAAAAA/wAA/wAAAAAJAAAACAAzMzI3NjI2OTMyNzY4NAEAAIAyDf8AAP8AAAAACAAAABzxKQgAAA==')
+        except BlackboxProcessError as e:
+            self.fail(e)
+        self.assertEqual(actual, expected)
+
+    def test_ndrdump_fuzzed_IOXIDResolver_ResolveOxid(self):
+        expected = '''pull returned Character Conversion Error
+'''
+        try:
+            actual = self.check_exit_code(
+                'ndrdump IOXIDResolver ResolveOxid out ' +\
+                '--base64-input --input=' +\
+                'c87PMf7CBAUAAAAADgQMBASjfPqKw0KPld6DY87PMfQ=',
+                2)
+        except BlackboxProcessError as e:
+            self.fail(e)
+        self.assertRegex(actual.decode('utf8'), expected + "$")
+
+    def test_ndrdump_fuzzed_IOXIDResolver_ResolveOxid2(self):
+        expected = '''pull returned Buffer Size Error
+'''
+        try:
+            actual = self.check_exit_code(
+                'ndrdump IOXIDResolver ResolveOxid2 out ' +\
+                '--base64-input --input=' +\
+                
'AAAAAQ0K9Q0AAAAAAAAAA6ampqampqampqampqampqampqampqamNAAAAAAtNDQ=',
+                2)
+        except BlackboxProcessError as e:
+            self.fail(e)
+        self.assertRegex(actual.decode('utf8'), expected + "$")
+
+    def test_ndrdump_fuzzed_IOXIDResolver_ServerAlive2(self):
+        expected = b'''pull returned Success
+WARNING! 46 unread bytes
+[0000] 0D 36 0A 0A 0A 0A 0A 00   00 00 00 00 00 00 03 00   .6...... ........
+[0010] 00 00 01 00 00 33 39 36   31 36 31 37 37 36 38 34   .....396 16177684
+[0020] 32 34 FC 85 AC 49 0B 61   87 0A 0A 0A F5 00         24...I.a ......
+    ServerAlive: struct ServerAlive
+        out: struct ServerAlive
+            result                   : DOS code 0x01000000
+dump OK
+'''
+        try:
+            actual = self.check_output(
+                'ndrdump IOXIDResolver ServerAlive out ' +\
+                '--base64-input --input=' +\
+                
'AAAAAQ02CgoKCgoAAAAAAAAAAwAAAAEAADM5NjE2MTc3Njg0MjT8haxJC2GHCgoK9QA=')
+        except BlackboxProcessError as e:
+            self.fail(e)
+        self.assertEqual(actual, expected)
+
+    def test_ndrdump_fuzzed_IRemoteActivation_RemoteActivation(self):
+        expected = '''pull returned Buffer Size Error
+'''
+        try:
+            actual = self.check_exit_code(
+                'ndrdump IRemoteActivation RemoteActivation out ' +\
+                '--base64-input --input=' +\
+                
'AAAAAQAAAAAAAABKAAD/AAAAAP4AAAAAAAAASgAAAAAAAAABIiIjIiIiIiIiIiIiIiMiAAAAAAD/AAAAAAAA',
+                2)
+        except BlackboxProcessError as e:
+            self.fail(e)
+        self.assertRegex(actual.decode('utf8'), expected + "$")
+
+    def test_ndrdump_fuzzed_ntlmsssp_AUTHENTICATE_MESSAGE(self):
+        expected = 
open(self.data_path("fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt")).read()
+        try:
+            actual = self.check_output(
+                "ndrdump ntlmssp AUTHENTICATE_MESSAGE struct --base64-input %s 
--validate" %
+                self.data_path("fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt"))
+        except BlackboxProcessError as e:
+            self.fail(e)
+        # check_output will return bytes
+        # convert expected to bytes for python 3
+        self.assertEqual(actual, expected.encode('utf-8'))
diff --git a/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt 
b/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt
new file mode 100644
index 00000000000..0a10ab03911
--- /dev/null
+++ b/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.b64.txt
@@ -0,0 +1 @@
+AA4AAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAzOQAAAAAAAAABAAAAAAAAAAD//gAAAAAAAAAABDMyMTUyMTE1MDI2MzE0Njg3/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+5+T2dekB8vfW3brf3WrDRDczOQAAAAA=
diff --git a/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt 
b/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt
new file mode 100644
index 00000000000..8dbe6e6dac2
--- /dev/null
+++ b/source4/librpc/tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt
@@ -0,0 +1,134 @@
+pull returned Success
+WARNING! 188 unread bytes
+[0000] 04 33 32 31 35 32 31 31   35 30 32 36 33 31 34 36   .3215211 50263146
+[0010] 38 37 FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   87...... ........
+[0020] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0030] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0040] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0050] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0060] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0070] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0080] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[0090] FE FE FE FE FE FE FE FE   FE FE FE FE FE FE FE FE   ........ ........
+[00A0] FE FE FE FE FE E7 E4 F6   75 E9 01 F2 F7 D6 DD BA   ........ u.......
+[00B0] DF DD 6A C3 44 37 33 39   00 00 00 00               ..j.D739 ....
+    AUTHENTICATE_MESSAGE: struct AUTHENTICATE_MESSAGE
+        Signature                : ''
+        MessageType              : UNKNOWN_ENUM_VALUE (0)
+        LmChallengeResponseLen   : 0x0000 (0)
+        LmChallengeResponseMaxLen: 0x0000 (0)
+        LmChallengeResponse      : NULL
+        NtChallengeResponseLen   : 0x0000 (0)
+        NtChallengeResponseMaxLen: 0x0000 (0)
+        NtChallengeResponse      : NULL
+        DomainNameLen            : 0x0000 (0)
+        DomainNameMaxLen         : 0x0000 (0)
+        DomainName               : NULL
+        UserNameLen              : 0x0000 (0)
+        UserNameMaxLen           : 0x0001 (1)


-- 
Samba Shared Repository

Reply via email to