diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2007-02-27 18:52:38 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:18:14 -0500 |
commit | 2b5d317af191256abea65328ce8d8a8833dcae69 (patch) | |
tree | f13a55d67fa26b4489da5ef99bf80e883929835b /source3 | |
parent | 2838d7499cbd5b7ebade52321985244aee9a9f70 (diff) | |
download | samba-2b5d317af191256abea65328ce8d8a8833dcae69.tar.gz samba-2b5d317af191256abea65328ce8d8a8833dcae69.tar.xz samba-2b5d317af191256abea65328ce8d8a8833dcae69.zip |
r21565: Import ndrdump (doesn't compile yet, needs table support functions).
(This used to be commit 9a9b9421673ed1c455658d8ae79d7a1522a1baa7)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/Makefile.in | 22 | ||||
-rw-r--r-- | source3/librpc/gen_ndr/tables.c | 59 | ||||
-rwxr-xr-x | source3/librpc/tables.pl | 89 | ||||
-rw-r--r-- | source3/librpc/tools/ndrdump.c | 411 | ||||
-rw-r--r-- | source3/script/build_idl.sh | 3 |
5 files changed, 579 insertions, 5 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 435bded9749..8c32aa6a069 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -213,9 +213,11 @@ ERRORMAP_OBJ = libsmb/errormap.o PASSCHANGE_OBJ = libsmb/passchange.o + LIBNDR_OBJ = librpc/ndr/ndr_basic.o librpc/ndr/ndr.o librpc/ndr/ndr_misc.o \ - librpc/ndr/ndr_sec_helper.o librpc/ndr/ndr_string.o librpc/ndr/sid.o \ - rpc_client/ndr.o + librpc/ndr/ndr_sec_helper.o librpc/ndr/ndr_string.o librpc/ndr/sid.o + +RPCCLIENT_NDR_OBJ = rpc_client/ndr.o LIBNDR_GEN_OBJ = librpc/gen_ndr/ndr_unixinfo.o librpc/gen_ndr/ndr_lsa.o \ librpc/gen_ndr/ndr_dfs.o librpc/gen_ndr/ndr_echo.o \ @@ -326,7 +328,7 @@ LIBMSRPC_GEN_OBJ = librpc/gen_ndr/cli_unixinfo.o librpc/gen_ndr/cli_lsa.o \ librpc/gen_ndr/cli_srvsvc.o \ librpc/gen_ndr/cli_winreg.o librpc/gen_ndr/cli_initshutdown.o \ librpc/gen_ndr/cli_eventlog.o \ - $(LIBNDR_GEN_OBJ) $(LIBNDR_OBJ) + $(LIBNDR_GEN_OBJ) $(LIBNDR_OBJ) $(RPCCLIENT_NDR_OBJ) REGOBJS_OBJ = registry/reg_objects.o @@ -718,6 +720,11 @@ TALLOCTORT_OBJ = lib/talloc/testsuite.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ REPLACETORT_OBJ = lib/replace/test/testsuite.o lib/replace/test/os2_delete.o \ $(LIBREPLACE_OBJ) +NDRDUMP_OBJ = librpc/tools/ndrdump.o \ + $(PARAM_OBJ) $(LIBNDR_OBJ) $(LIBNDR_GEN_OBJ) \ + $(LIBSAMBA_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ + $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(POPT_OBJ) $(SECRETS_OBJ) + RPCTORTURE_OBJ = torture/rpctorture.o \ rpcclient/display.o \ rpcclient/cmd_lsarpc.o \ @@ -733,8 +740,8 @@ DEBUG2HTML_OBJ = utils/debug2html.o utils/debugparse.o SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(SECRETS_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) -PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) $(LIBNDR_GEN_OBJ) \ - $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(LIBSMB_OBJ) \ +PROTO_OBJ = $(SMBD_OBJ_MAIN) $(LIBNDR_OBJ) $(RPCCLIENT_NDR_OBJ) \ + $(LIBNDR_GEN_OBJ) $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(LIBSMB_OBJ) \ $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \ $(LIBMSRPC_OBJ) @SMBWRAP_OBJS@ \ $(LIB_WITH_PROTO_OBJ) \ @@ -1181,6 +1188,11 @@ bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) +bin/ndrdump@EXEEXT@: $(NDRDUMP_OBJ) bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) -o $@ $(NDRDUMP_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) \ + @POPTLIBS@ @LDAP_LIBS@ + bin/debug2html@EXEEXT@: proto_exists $(DEBUG2HTML_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) diff --git a/source3/librpc/gen_ndr/tables.c b/source3/librpc/gen_ndr/tables.c new file mode 100644 index 00000000000..d2601499012 --- /dev/null +++ b/source3/librpc/gen_ndr/tables.c @@ -0,0 +1,59 @@ + +/* Automatically generated by tables.pl. DO NOT EDIT */ + +#include "includes.h" +#include "librpc/rpc/dcerpc.h" +#include "librpc/rpc/dcerpc_table.h" +#include "librpc/gen_ndr/ndr_dfs.h" +#include "librpc/gen_ndr/ndr_echo.h" +#include "librpc/gen_ndr/ndr_eventlog.h" +#include "librpc/gen_ndr/ndr_initshutdown.h" +#include "librpc/gen_ndr/ndr_lsa.h" +#include "librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_srvsvc.h" +#include "librpc/gen_ndr/ndr_svcctl.h" +#include "librpc/gen_ndr/ndr_unixinfo.h" +#include "librpc/gen_ndr/ndr_winreg.h" +#include "librpc/gen_ndr/ndr_wkssvc.h" + +NTSTATUS dcerpc_register_builtin_interfaces(void) +{ + NTSTATUS status; + + status = librpc_register_interface(&dcerpc_table_netdfs); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_rpcecho); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_eventlog); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_initshutdown); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_lsarpc); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_netlogon); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_srvsvc); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_svcctl); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_unixinfo); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_winreg); + if (NT_STATUS_IS_ERR(status)) return status; + + status = librpc_register_interface(&dcerpc_table_wkssvc); + if (NT_STATUS_IS_ERR(status)) return status; + + + + return NT_STATUS_OK; +} diff --git a/source3/librpc/tables.pl b/source3/librpc/tables.pl new file mode 100755 index 00000000000..9ad0675cb23 --- /dev/null +++ b/source3/librpc/tables.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl -w + +################################################### +# package to produce a table of all idl parsers +# Copyright tridge@samba.org 2003 +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +use strict; + +use Getopt::Long; +use File::Basename; + +my $opt_output = 'librpc/gen_ndr/tables.c'; +my $opt_help = 0; + + +######################################### +# display help text +sub ShowHelp() +{ + print " + perl DCE/RPC interface table generator + Copyright (C) tridge\@samba.org + + Usage: tables.pl [options] <idlfile> + + \n"; + exit(0); +} + +# main program +GetOptions ( + 'help|h|?' => \$opt_help, + 'output=s' => \$opt_output, + ); + +if ($opt_help) { + ShowHelp(); + exit(0); +} + +my $init_fns = ""; + +################################### +# extract table entries from 1 file +sub process_file($) +{ + my $filename = shift; + open(FILE, $filename) || die "unable to open $filename\n"; + my $found = 0; + + while (my $line = <FILE>) { + if ($line =~ /extern const struct dcerpc_interface_table (\w+);/) { + $found = 1; + $init_fns.="\tstatus = librpc_register_interface(&$1);\n"; + $init_fns.="\tif (NT_STATUS_IS_ERR(status)) return status;\n\n"; + } + } + + if ($found) { + print "#include \"$filename\"\n"; + } + + close(FILE); +} + +print <<EOF; + +/* Automatically generated by tables.pl. DO NOT EDIT */ + +#include "includes.h" +#include "librpc/rpc/dcerpc.h" +#include "librpc/rpc/dcerpc_table.h" +EOF + +process_file($_) foreach (@ARGV); + +print <<EOF; + +NTSTATUS dcerpc_register_builtin_interfaces(void) +{ + NTSTATUS status; + +$init_fns + + return NT_STATUS_OK; +} +EOF diff --git a/source3/librpc/tools/ndrdump.c b/source3/librpc/tools/ndrdump.c new file mode 100644 index 00000000000..e1c7c41f12f --- /dev/null +++ b/source3/librpc/tools/ndrdump.c @@ -0,0 +1,411 @@ +/* + Unix SMB/CIFS implementation. + SMB torture tester + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Jelmer Vernooij 2006 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "system/locale.h" + +static const struct dcerpc_interface_call *find_function( + const struct dcerpc_interface_table *p, + const char *function) +{ + int i; + if (isdigit(function[0])) { + i = strtol(function, NULL, 0); + return &p->calls[i]; + } + for (i=0;i<p->num_calls;i++) { + if (strcmp(p->calls[i].name, function) == 0) { + break; + } + } + if (i == p->num_calls) { + printf("Function '%s' not found\n", function); + exit(1); + } + return &p->calls[i]; +} + + +static void show_pipes(void) +{ + const struct dcerpc_interface_list *l; + printf("\nYou must specify a pipe\n"); + printf("known pipes are:\n"); + for (l=librpc_dcerpc_pipes();l;l=l->next) { + if(l->table->helpstring) { + printf("\t%s - %s\n", l->table->name, l->table->helpstring); + } else { + printf("\t%s\n", l->table->name); + } + } + exit(1); +} + +static void show_functions(const struct dcerpc_interface_table *p) +{ + int i; + printf("\nYou must specify a function\n"); + printf("known functions on '%s' are:\n", p->name); + for (i=0;i<p->num_calls;i++) { + printf("\t0x%02x (%2d) %s\n", i, i, p->calls[i].name); + } + exit(1); +} + +static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size) +{ + int num_read, total_len = 0; + char buf[255]; + char *result = NULL; + + while((num_read = read(STDIN_FILENO, buf, 255)) > 0) { + + if (result) { + result = (char *) talloc_realloc( + mem_ctx, result, char *, total_len + num_read); + } else { + result = talloc_size(mem_ctx, num_read); + } + + memcpy(result + total_len, buf, num_read); + + total_len += num_read; + } + + if (size) + *size = total_len; + + return result; +} + +const struct dcerpc_interface_table *load_iface_from_plugin(const char *plugin, const char *pipe_name) +{ + const struct dcerpc_interface_table *p; + void *handle; + char *symbol; + + handle = dlopen(plugin, RTLD_NOW); + if (handle == NULL) { + printf("%s: Unable to open: %s\n", plugin, dlerror()); + return NULL; + } + + symbol = talloc_asprintf(NULL, "dcerpc_table_%s", pipe_name); + p = dlsym(handle, symbol); + + if (!p) { + printf("%s: Unable to find DCE/RPC interface table for '%s': %s\n", plugin, pipe_name, dlerror()); + talloc_free(symbol); + return NULL; + } + + talloc_free(symbol); + + return p; +} + + int main(int argc, const char *argv[]) +{ + const struct dcerpc_interface_table *p = NULL; + const struct dcerpc_interface_call *f; + const char *pipe_name, *function, *inout, *filename; + uint8_t *data; + size_t size; + DATA_BLOB blob; + struct ndr_pull *ndr_pull; + struct ndr_print *ndr_print; + TALLOC_CTX *mem_ctx; + int flags; + poptContext pc; + NTSTATUS status; + void *st; + void *v_st; + const char *ctx_filename = NULL; + const char *plugin = NULL; + bool validate = false; + bool dumpdata = false; + int opt; + enum {OPT_CONTEXT_FILE=1000, OPT_VALIDATE, OPT_DUMP_DATA, OPT_LOAD_DSO}; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"context-file", 'c', POPT_ARG_STRING, NULL, OPT_CONTEXT_FILE, "In-filename to parse first", "CTX-FILE" }, + {"validate", 0, POPT_ARG_NONE, NULL, OPT_VALIDATE, "try to validate the data", NULL }, + {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMP_DATA, "dump the hex data", NULL }, + {"load-dso", 'l', POPT_ARG_STRING, NULL, OPT_LOAD_DSO, "load from shared object file", NULL }, + POPT_COMMON_SAMBA + POPT_COMMON_VERSION + { NULL } + }; + + dcerpc_table_init(); + + pc = poptGetContext("ndrdump", argc, argv, long_options, 0); + + poptSetOtherOptionHelp( + pc, "<pipe|uuid> <function> <inout> [<filename>]"); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case OPT_CONTEXT_FILE: + ctx_filename = poptGetOptArg(pc); + break; + case OPT_VALIDATE: + validate = true; + break; + case OPT_DUMP_DATA: + dumpdata = true; + break; + case OPT_LOAD_DSO: + plugin = poptGetOptArg(pc); + break; + } + } + + pipe_name = poptGetArg(pc); + + if (!pipe_name) { + poptPrintUsage(pc, stderr, 0); + show_pipes(); + exit(1); + } + + if (plugin != NULL) { + p = load_iface_from_plugin(plugin, pipe_name); + } + + if (!p) { + p = idl_iface_by_name(pipe_name); + } + + if (!p) { + struct GUID uuid; + + status = GUID_from_string(pipe_name, &uuid); + + if (NT_STATUS_IS_OK(status)) { + p = idl_iface_by_uuid(&uuid); + } + } + + if (!p) { + printf("Unknown pipe or UUID '%s'\n", pipe_name); + exit(1); + } + + function = poptGetArg(pc); + inout = poptGetArg(pc); + filename = poptGetArg(pc); + + if (!function || !inout) { + poptPrintUsage(pc, stderr, 0); + show_functions(p); + exit(1); + } + + if (strcmp(inout, "in") == 0 || + strcmp(inout, "request") == 0) { + flags = NDR_IN; + } else if (strcmp(inout, "out") == 0 || + strcmp(inout, "response") == 0) { + flags = NDR_OUT; + } else { + printf("Bad inout value '%s'\n", inout); + exit(1); + } + + f = find_function(p, function); + + mem_ctx = talloc_init("ndrdump"); + + st = talloc_zero_size(mem_ctx, f->struct_size); + if (!st) { + printf("Unable to allocate %d bytes\n", (int)f->struct_size); + 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); + exit(1); + } + + if (ctx_filename) { + if (flags == NDR_IN) { + printf("Context file can only be used for \"out\" packages\n"); + exit(1); + } + + data = (uint8_t *)file_load(ctx_filename, &size, 0); + if (!data) { + perror(ctx_filename); + exit(1); + } + + blob.data = data; + blob.length = size; + + ndr_pull = ndr_pull_init_blob(&blob, mem_ctx); + ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC; + + status = f->ndr_pull(ndr_pull, NDR_IN, st); + + if (ndr_pull->offset != ndr_pull->data_size) { + printf("WARNING! %d unread bytes while parsing context file\n", ndr_pull->data_size - ndr_pull->offset); + } + + if (!NT_STATUS_IS_OK(status)) { + printf("pull for context file returned %s\n", nt_errstr(status)); + exit(1); + } + memcpy(v_st, st, f->struct_size); + } + + if (filename) + data = (uint8_t *)file_load(filename, &size, 0); + else + data = (uint8_t *)stdin_load(mem_ctx, &size); + + if (!data) { + if (filename) + perror(filename); + else + perror("stdin"); + exit(1); + } + + blob.data = data; + blob.length = size; + + ndr_pull = ndr_pull_init_blob(&blob, mem_ctx); + ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC; + + status = f->ndr_pull(ndr_pull, flags, st); + + printf("pull returned %s\n", nt_errstr(status)); + + if (ndr_pull->offset != ndr_pull->data_size) { + printf("WARNING! %d unread bytes\n", ndr_pull->data_size - ndr_pull->offset); + dump_data(0, (const char *)ndr_pull->data+ndr_pull->offset, ndr_pull->data_size - ndr_pull->offset); + } + + if (dumpdata) { + printf("%d bytes consumed\n", ndr_pull->offset); + dump_data(0, (const char *)blob.data, blob.length); + } + + ndr_print = talloc_zero(mem_ctx, struct ndr_print); + ndr_print->print = ndr_print_debug_helper; + ndr_print->depth = 1; + f->ndr_print(ndr_print, function, flags, st); + + if (!NT_STATUS_IS_OK(status)) { + printf("dump FAILED\n"); + exit(1); + } + + if (validate) { + DATA_BLOB v_blob; + struct ndr_push *ndr_v_push; + struct ndr_pull *ndr_v_pull; + struct ndr_print *ndr_v_print; + uint32_t i; + uint8_t byte_a, byte_b; + bool differ; + + ndr_v_push = ndr_push_init_ctx(mem_ctx); + + status = f->ndr_push(ndr_v_push, flags, st); + if (!NT_STATUS_IS_OK(status)) { + printf("validate push FAILED\n"); + exit(1); + } + + v_blob = ndr_push_blob(ndr_v_push); + + if (dumpdata) { + printf("%ld bytes generated (validate)\n", (long)v_blob.length); + dump_data(0, (const char *)v_blob.data, v_blob.length); + } + + ndr_v_pull = ndr_pull_init_blob(&v_blob, mem_ctx); + ndr_v_pull->flags |= LIBNDR_FLAG_REF_ALLOC; + + status = f->ndr_pull(ndr_v_pull, flags, v_st); + if (!NT_STATUS_IS_OK(status)) { + printf("validate pull FAILED\n"); + exit(1); + } + + printf("pull returned %s\n", nt_errstr(status)); + + if (ndr_v_pull->offset != ndr_v_pull->data_size) { + printf("WARNING! %d unread bytes in validation\n", ndr_v_pull->data_size - ndr_v_pull->offset); + dump_data(0, (const char *)ndr_v_pull->data+ndr_v_pull->offset, ndr_v_pull->data_size - ndr_v_pull->offset); + } + + ndr_v_print = talloc_zero(mem_ctx, struct ndr_print); + ndr_v_print->print = ndr_print_debug_helper; + ndr_v_print->depth = 1; + f->ndr_print(ndr_v_print, function, flags, v_st); + + if (blob.length != v_blob.length) { + printf("WARNING! orig bytes:%u validated pushed bytes:%u\n", blob.length, v_blob.length); + } + + if (ndr_pull->offset != ndr_v_pull->offset) { + printf("WARNING! orig pulled bytes:%u validated pulled bytes:%u\n", ndr_pull->offset, ndr_v_pull->offset); + } + + differ = false; + byte_a = 0x00; + byte_b = 0x00; + for (i=0; i < blob.length; i++) { + byte_a = blob.data[i]; + + if (i == v_blob.length) { + byte_b = 0x00; + differ = true; + break; + } + + byte_b = v_blob.data[i]; + + if (byte_a != byte_b) { + differ = true; + break; + } + } + if (differ) { + printf("WARNING! orig and validated differ at byte 0x%02X (%u)\n", i, i); + printf("WARNING! orig byte[0x%02X] = 0x%02X validated byte[0x%02X] = 0x%02X\n", + i, byte_a, i, byte_b); + } + } + + printf("dump OK\n"); + + talloc_free(mem_ctx); + + poptFreeContext(pc); + + return 0; +} diff --git a/source3/script/build_idl.sh b/source3/script/build_idl.sh index 8ec5f4de24e..77f37d8e75e 100644 --- a/source3/script/build_idl.sh +++ b/source3/script/build_idl.sh @@ -52,6 +52,9 @@ done touch librpc/gen_ndr/ndr_dcerpc.h +echo Generating librpc/gen_ndr/tables.c +./librpc/tables.pl --output=librpc/gen_ndr/tables.c librpc/gen_ndr/*.h > librpc/gen_ndr/tables.c + cd ${oldpwd} exit 0 |