• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/torture/rpc/
1/*
2   Unix SMB/CIFS implementation.
3
4   auto-idl scanner
5
6   Copyright (C) Andrew Tridgell 2003
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "torture/torture.h"
24#include "librpc/gen_ndr/ndr_drsuapi_c.h"
25#include "librpc/gen_ndr/ndr_misc.h"
26#include "librpc/ndr/ndr_table.h"
27#include "torture/rpc/rpc.h"
28#include "librpc/rpc/dcerpc_proto.h"
29
30
31#if 1
32/*
33  get a DRSUAPI policy handle
34*/
35static bool get_policy_handle(struct dcerpc_pipe *p,
36			      TALLOC_CTX *mem_ctx,
37			      struct policy_handle *handle)
38{
39	NTSTATUS status;
40	struct drsuapi_DsBind r;
41
42	ZERO_STRUCT(r);
43	r.out.bind_handle = handle;
44
45	status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
46	if (!NT_STATUS_IS_OK(status)) {
47		printf("drsuapi_DsBind failed - %s\n", nt_errstr(status));
48		return false;
49	}
50
51	return true;
52}
53#else
54/*
55  get a SAMR handle
56*/
57static bool get_policy_handle(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
58			      struct policy_handle *handle)
59{
60	NTSTATUS status;
61	struct samr_Connect r;
62
63	r.in.system_name = 0;
64	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
65	r.out.connect_handle = handle;
66
67	status = dcerpc_samr_Connect(p, mem_ctx, &r);
68	if (!NT_STATUS_IS_OK(status)) {
69		printf("samr_Connect failed - %s\n", nt_errstr(status));
70		return false;
71	}
72
73	return true;
74}
75#endif
76
77static void fill_blob_handle(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
78			     struct policy_handle *handle)
79{
80	DATA_BLOB b2;
81
82	if (blob->length < 20) {
83		return;
84	}
85
86	ndr_push_struct_blob(&b2, mem_ctx, NULL, handle, (ndr_push_flags_fn_t)ndr_push_policy_handle);
87
88	memcpy(blob->data, b2.data, 20);
89}
90
91static void reopen(struct torture_context *tctx,
92		   struct dcerpc_pipe **p,
93		   const struct ndr_interface_table *iface)
94{
95	NTSTATUS status;
96
97	talloc_free(*p);
98
99	status = torture_rpc_connection(tctx, p, iface);
100	if (!NT_STATUS_IS_OK(status)) {
101		printf("Failed to reopen '%s' - %s\n", iface->name, nt_errstr(status));
102		exit(1);
103	}
104}
105
106static void print_depth(int depth)
107{
108	int i;
109	for (i=0;i<depth;i++) {
110		printf("    ");
111	}
112}
113
114static void test_ptr_scan(struct torture_context *tctx, const struct ndr_interface_table *iface,
115			  int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth);
116
117static void try_expand(struct torture_context *tctx, const struct ndr_interface_table *iface,
118		       int opnum, DATA_BLOB *base_in, int insert_ofs, int depth)
119{
120	DATA_BLOB stub_in, stub_out;
121	int n;
122	NTSTATUS status;
123	struct dcerpc_pipe *p = NULL;
124
125	reopen(tctx, &p, iface);
126
127	/* work out how much to expand to get a non fault */
128	for (n=0;n<2000;n++) {
129		stub_in = data_blob(NULL, base_in->length + n);
130		data_blob_clear(&stub_in);
131		memcpy(stub_in.data, base_in->data, insert_ofs);
132		memcpy(stub_in.data+insert_ofs+n, base_in->data+insert_ofs, base_in->length-insert_ofs);
133
134		status = dcerpc_request(p, NULL, opnum, tctx, &stub_in, &stub_out);
135
136		if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
137			print_depth(depth);
138			printf("expand by %d gives %s\n", n, nt_errstr(status));
139			if (n >= 4) {
140				test_ptr_scan(tctx, iface, opnum, &stub_in,
141					      insert_ofs, insert_ofs+n, depth+1);
142			}
143			return;
144		} else {
145#if 0
146			print_depth(depth);
147			printf("expand by %d gives fault %s\n", n, dcerpc_errstr(tctx, p->last_fault_code));
148#endif
149		}
150		if (p->last_fault_code == 5) {
151			reopen(tctx, &p, iface);
152		}
153	}
154
155	talloc_free(p);
156}
157
158
159static void test_ptr_scan(struct torture_context *tctx, const struct ndr_interface_table *iface,
160			  int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth)
161{
162	DATA_BLOB stub_in, stub_out;
163	int ofs;
164	NTSTATUS status;
165	struct dcerpc_pipe *p = NULL;
166
167	reopen(tctx, &p, iface);
168
169	stub_in = data_blob(NULL, base_in->length);
170	memcpy(stub_in.data, base_in->data, base_in->length);
171
172	/* work out which elements are pointers */
173	for (ofs=min_ofs;ofs<=max_ofs-4;ofs+=4) {
174		SIVAL(stub_in.data, ofs, 1);
175		status = dcerpc_request(p, NULL, opnum, tctx, &stub_in, &stub_out);
176
177		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
178			print_depth(depth);
179			printf("possible ptr at ofs %d - fault %s\n",
180			       ofs-min_ofs, dcerpc_errstr(tctx, p->last_fault_code));
181			if (p->last_fault_code == 5) {
182				reopen(tctx, &p, iface);
183			}
184			if (depth == 0) {
185				try_expand(tctx, iface, opnum, &stub_in, ofs+4, depth+1);
186			} else {
187				try_expand(tctx, iface, opnum, &stub_in, max_ofs, depth+1);
188			}
189			SIVAL(stub_in.data, ofs, 0);
190			continue;
191		}
192		SIVAL(stub_in.data, ofs, 0);
193	}
194
195	talloc_free(p);
196}
197
198
199static void test_scan_call(struct torture_context *tctx, const struct ndr_interface_table *iface, int opnum)
200{
201	DATA_BLOB stub_in, stub_out;
202	int i;
203	NTSTATUS status;
204	struct dcerpc_pipe *p = NULL;
205	struct policy_handle handle;
206
207	reopen(tctx, &p, iface);
208
209	get_policy_handle(p, tctx, &handle);
210
211	/* work out the minimum amount of input data */
212	for (i=0;i<2000;i++) {
213		stub_in = data_blob(NULL, i);
214		data_blob_clear(&stub_in);
215
216
217		status = dcerpc_request(p, NULL, opnum, tctx, &stub_in, &stub_out);
218
219		if (NT_STATUS_IS_OK(status)) {
220			printf("opnum %d   min_input %d - output %d\n",
221			       opnum, (int)stub_in.length, (int)stub_out.length);
222			dump_data(0, stub_out.data, stub_out.length);
223			talloc_free(p);
224			test_ptr_scan(tctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
225			return;
226		}
227
228		fill_blob_handle(&stub_in, tctx, &handle);
229
230		status = dcerpc_request(p, NULL, opnum, tctx, &stub_in, &stub_out);
231
232		if (NT_STATUS_IS_OK(status)) {
233			printf("opnum %d   min_input %d - output %d (with handle)\n",
234			       opnum, (int)stub_in.length, (int)stub_out.length);
235			dump_data(0, stub_out.data, stub_out.length);
236			talloc_free(p);
237			test_ptr_scan(tctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
238			return;
239		}
240
241		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
242			printf("opnum %d  size %d fault %s\n", opnum, i, dcerpc_errstr(tctx, p->last_fault_code));
243			if (p->last_fault_code == 5) {
244				reopen(tctx, &p, iface);
245			}
246			continue;
247		}
248
249		printf("opnum %d  size %d error %s\n", opnum, i, nt_errstr(status));
250	}
251
252	printf("opnum %d minimum not found!?\n", opnum);
253	talloc_free(p);
254}
255
256
257static void test_auto_scan(struct torture_context *tctx, const struct ndr_interface_table *iface)
258{
259	test_scan_call(tctx, iface, 2);
260}
261
262bool torture_rpc_autoidl(struct torture_context *torture)
263{
264	const struct ndr_interface_table *iface;
265
266	iface = ndr_table_by_name("drsuapi");
267	if (!iface) {
268		printf("Unknown interface!\n");
269		return false;
270	}
271
272	printf("\nProbing pipe '%s'\n", iface->name);
273
274	test_auto_scan(torture, iface);
275
276	return true;
277}
278