2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #if (_SAMBA_BUILD_ >= 4)
24 #include "lib/cmdline/popt_common.h"
25 #include "system/filesys.h"
26 #include "system/locale.h"
27 #include "librpc/rpc/dcerpc.h"
28 #include "librpc/rpc/dcerpc_table.h"
31 static const struct dcerpc_interface_call
*find_function(
32 const struct dcerpc_interface_table
*p
,
36 if (isdigit(function
[0])) {
37 i
= strtol(function
, NULL
, 0);
40 for (i
=0;i
<p
->num_calls
;i
++) {
41 if (strcmp(p
->calls
[i
].name
, function
) == 0) {
45 if (i
== p
->num_calls
) {
46 printf("Function '%s' not found\n", function
);
52 #if (_SAMBA_BUILD_ >= 4)
54 static void show_pipes(void)
56 const struct dcerpc_interface_list
*l
;
57 printf("\nYou must specify a pipe\n");
58 printf("known pipes are:\n");
59 for (l
=librpc_dcerpc_pipes();l
;l
=l
->next
) {
60 if(l
->table
->helpstring
) {
61 printf("\t%s - %s\n", l
->table
->name
, l
->table
->helpstring
);
63 printf("\t%s\n", l
->table
->name
);
71 static void show_functions(const struct dcerpc_interface_table
*p
)
74 printf("\nYou must specify a function\n");
75 printf("known functions on '%s' are:\n", p
->name
);
76 for (i
=0;i
<p
->num_calls
;i
++) {
77 printf("\t0x%02x (%2d) %s\n", i
, i
, p
->calls
[i
].name
);
82 static char *stdin_load(TALLOC_CTX
*mem_ctx
, size_t *size
)
84 int num_read
, total_len
= 0;
88 while((num_read
= read(STDIN_FILENO
, buf
, 255)) > 0) {
91 result
= (char *) talloc_realloc(
92 mem_ctx
, result
, char *, total_len
+ num_read
);
94 result
= (char *) talloc_size(mem_ctx
, num_read
);
97 memcpy(result
+ total_len
, buf
, num_read
);
99 total_len
+= num_read
;
108 static const struct dcerpc_interface_table
*load_iface_from_plugin(const char *plugin
, const char *pipe_name
)
110 const struct dcerpc_interface_table
*p
;
114 handle
= dlopen(plugin
, RTLD_NOW
);
115 if (handle
== NULL
) {
116 printf("%s: Unable to open: %s\n", plugin
, dlerror());
120 symbol
= talloc_asprintf(NULL
, "dcerpc_table_%s", pipe_name
);
121 p
= (const struct dcerpc_interface_table
*)dlsym(handle
, symbol
);
124 printf("%s: Unable to find DCE/RPC interface table for '%s': %s\n", plugin
, pipe_name
, dlerror());
134 int main(int argc
, const char *argv
[])
136 const struct dcerpc_interface_table
*p
= NULL
;
137 const struct dcerpc_interface_call
*f
;
138 const char *pipe_name
, *function
, *inout
, *filename
;
142 struct ndr_pull
*ndr_pull
;
143 struct ndr_print
*ndr_print
;
150 const char *ctx_filename
= NULL
;
151 const char *plugin
= NULL
;
152 bool validate
= false;
153 bool dumpdata
= false;
155 enum {OPT_CONTEXT_FILE
=1000, OPT_VALIDATE
, OPT_DUMP_DATA
, OPT_LOAD_DSO
};
156 struct poptOption long_options
[] = {
158 {"context-file", 'c', POPT_ARG_STRING
, NULL
, OPT_CONTEXT_FILE
, "In-filename to parse first", "CTX-FILE" },
159 {"validate", 0, POPT_ARG_NONE
, NULL
, OPT_VALIDATE
, "try to validate the data", NULL
},
160 {"dump-data", 0, POPT_ARG_NONE
, NULL
, OPT_DUMP_DATA
, "dump the hex data", NULL
},
161 {"load-dso", 'l', POPT_ARG_STRING
, NULL
, OPT_LOAD_DSO
, "load from shared object file", NULL
},
167 #if (_SAMBA_BUILD_ >= 4)
170 /* Initialise samba stuff */
177 setup_logging(argv
[0],True
);
180 pc
= poptGetContext("ndrdump", argc
, argv
, long_options
, 0);
182 poptSetOtherOptionHelp(
183 pc
, "<pipe|uuid> <function> <inout> [<filename>]");
185 while ((opt
= poptGetNextOpt(pc
)) != -1) {
187 case OPT_CONTEXT_FILE
:
188 ctx_filename
= poptGetOptArg(pc
);
197 plugin
= poptGetOptArg(pc
);
202 pipe_name
= poptGetArg(pc
);
205 poptPrintUsage(pc
, stderr
, 0);
206 #if (_SAMBA_BUILD_ >= 4)
212 if (plugin
!= NULL
) {
213 p
= load_iface_from_plugin(plugin
, pipe_name
);
215 #if (_SAMBA_BUILD_ <= 3)
217 fprintf(stderr
, "Only loading from DSO's supported in Samba 3\n");
222 p
= idl_iface_by_name(pipe_name
);
228 status
= GUID_from_string(pipe_name
, &uuid
);
230 if (NT_STATUS_IS_OK(status
)) {
231 p
= idl_iface_by_uuid(&uuid
);
237 printf("Unknown pipe or UUID '%s'\n", pipe_name
);
241 function
= poptGetArg(pc
);
242 inout
= poptGetArg(pc
);
243 filename
= poptGetArg(pc
);
245 if (!function
|| !inout
) {
246 poptPrintUsage(pc
, stderr
, 0);
251 if (strcmp(inout
, "in") == 0 ||
252 strcmp(inout
, "request") == 0) {
254 } else if (strcmp(inout
, "out") == 0 ||
255 strcmp(inout
, "response") == 0) {
258 printf("Bad inout value '%s'\n", inout
);
262 f
= find_function(p
, function
);
264 mem_ctx
= talloc_init("ndrdump");
266 st
= talloc_zero_size(mem_ctx
, f
->struct_size
);
268 printf("Unable to allocate %d bytes\n", (int)f
->struct_size
);
272 v_st
= talloc_zero_size(mem_ctx
, f
->struct_size
);
274 printf("Unable to allocate %d bytes\n", (int)f
->struct_size
);
279 if (flags
== NDR_IN
) {
280 printf("Context file can only be used for \"out\" packages\n");
284 #if (_SAMBA_BUILD_ >= 4)
285 data
= (uint8_t *)file_load(ctx_filename
, &size
, mem_ctx
);
287 data
= (uint8_t *)file_load(ctx_filename
, &size
, 0);
290 perror(ctx_filename
);
297 ndr_pull
= ndr_pull_init_blob(&blob
, mem_ctx
);
298 ndr_pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
300 status
= f
->ndr_pull(ndr_pull
, NDR_IN
, st
);
302 if (ndr_pull
->offset
!= ndr_pull
->data_size
) {
303 printf("WARNING! %d unread bytes while parsing context file\n", ndr_pull
->data_size
- ndr_pull
->offset
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 printf("pull for context file returned %s\n", nt_errstr(status
));
310 memcpy(v_st
, st
, f
->struct_size
);
314 #if (_SAMBA_BUILD_ >= 4)
315 data
= (uint8_t *)file_load(filename
, &size
, mem_ctx
);
317 data
= (uint8_t *)file_load(filename
, &size
, 0);
320 data
= (uint8_t *)stdin_load(mem_ctx
, &size
);
333 ndr_pull
= ndr_pull_init_blob(&blob
, mem_ctx
);
334 ndr_pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
336 status
= f
->ndr_pull(ndr_pull
, flags
, st
);
338 printf("pull returned %s\n", nt_errstr(status
));
340 if (ndr_pull
->offset
!= ndr_pull
->data_size
) {
341 printf("WARNING! %d unread bytes\n", ndr_pull
->data_size
- ndr_pull
->offset
);
342 dump_data(0, ndr_pull
->data
+ndr_pull
->offset
, ndr_pull
->data_size
- ndr_pull
->offset
);
346 printf("%d bytes consumed\n", ndr_pull
->offset
);
347 dump_data(0, blob
.data
, blob
.length
);
350 ndr_print
= talloc_zero(mem_ctx
, struct ndr_print
);
351 ndr_print
->print
= ndr_print_debug_helper
;
352 ndr_print
->depth
= 1;
353 f
->ndr_print(ndr_print
, function
, flags
, st
);
355 if (!NT_STATUS_IS_OK(status
)) {
356 printf("dump FAILED\n");
362 struct ndr_push
*ndr_v_push
;
363 struct ndr_pull
*ndr_v_pull
;
364 struct ndr_print
*ndr_v_print
;
366 uint8_t byte_a
, byte_b
;
369 ndr_v_push
= ndr_push_init_ctx(mem_ctx
);
371 status
= f
->ndr_push(ndr_v_push
, flags
, st
);
372 if (!NT_STATUS_IS_OK(status
)) {
373 printf("validate push FAILED\n");
377 v_blob
= ndr_push_blob(ndr_v_push
);
380 printf("%ld bytes generated (validate)\n", (long)v_blob
.length
);
381 dump_data(0, v_blob
.data
, v_blob
.length
);
384 ndr_v_pull
= ndr_pull_init_blob(&v_blob
, mem_ctx
);
385 ndr_v_pull
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
387 status
= f
->ndr_pull(ndr_v_pull
, flags
, v_st
);
388 if (!NT_STATUS_IS_OK(status
)) {
389 printf("validate pull FAILED\n");
393 printf("pull returned %s\n", nt_errstr(status
));
395 if (ndr_v_pull
->offset
!= ndr_v_pull
->data_size
) {
396 printf("WARNING! %d unread bytes in validation\n", ndr_v_pull
->data_size
- ndr_v_pull
->offset
);
397 dump_data(0, ndr_v_pull
->data
+ndr_v_pull
->offset
, ndr_v_pull
->data_size
- ndr_v_pull
->offset
);
400 ndr_v_print
= talloc_zero(mem_ctx
, struct ndr_print
);
401 ndr_v_print
->print
= ndr_print_debug_helper
;
402 ndr_v_print
->depth
= 1;
403 f
->ndr_print(ndr_v_print
, function
, flags
, v_st
);
405 if (blob
.length
!= v_blob
.length
) {
406 printf("WARNING! orig bytes:%u validated pushed "
407 "bytes:%u\n", (unsigned int)blob
.length
,
408 (unsigned int)v_blob
.length
);
411 if (ndr_pull
->offset
!= ndr_v_pull
->offset
) {
412 printf("WARNING! orig pulled bytes:%u validated pulled bytes:%u\n", ndr_pull
->offset
, ndr_v_pull
->offset
);
418 for (i
=0; i
< blob
.length
; i
++) {
419 byte_a
= blob
.data
[i
];
421 if (i
== v_blob
.length
) {
427 byte_b
= v_blob
.data
[i
];
429 if (byte_a
!= byte_b
) {
435 printf("WARNING! orig and validated differ at byte 0x%02X (%u)\n", i
, i
);
436 printf("WARNING! orig byte[0x%02X] = 0x%02X validated byte[0x%02X] = 0x%02X\n",
437 i
, byte_a
, i
, byte_b
);
443 talloc_free(mem_ctx
);