r2100: rework the dcerpc client side library so that it is async. We now
[bbaumbach/samba-autobuild/.git] / source4 / torture / rpc / drsuapi.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    DRSUapi tests
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher 2004
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 static const char *machine_password;
27
28 #define TEST_MACHINE_NAME "torturetest"
29
30 #if 0
31 static void reopen(struct dcerpc_pipe **p, const struct dcerpc_interface_table *iface)
32 {
33         NTSTATUS status;
34
35         if (*p) {
36                 dcerpc_pipe_close(*p);
37         }
38
39         status = torture_rpc_connection(p, iface->endpoints->names[0], iface->uuid, iface->if_version);
40         if (!NT_STATUS_IS_OK(status)) {
41                 printf("Failed to reopen '%s' - %s\n", iface->name, nt_errstr(status));
42                 exit(1);
43         }
44 }
45
46 static void print_depth(int depth)
47 {
48         int i;
49         for (i=0;i<depth;i++) {
50                 printf("    ");
51         }
52 }
53
54 static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
55                           int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth);
56
57 static void try_expand(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
58                        int opnum, DATA_BLOB *base_in, int insert_ofs, int depth)
59 {
60         DATA_BLOB stub_in, stub_out;
61         int n;
62         NTSTATUS status;
63         struct dcerpc_pipe *p = NULL;
64
65         reopen(&p, iface);
66
67         /* work out how much to expand to get a non fault */
68         for (n=0;n<2000;n++) {
69                 stub_in = data_blob(NULL, base_in->length + n);
70                 data_blob_clear(&stub_in);
71                 memcpy(stub_in.data, base_in->data, insert_ofs);
72                 memcpy(stub_in.data+insert_ofs+n, base_in->data+insert_ofs, base_in->length-insert_ofs);
73
74                 status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
75
76                 if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
77                         print_depth(depth);
78                         printf("expand by %d gives %s\n", n, nt_errstr(status));
79                         if (n >= 4) {
80                                 test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 
81                                               insert_ofs, insert_ofs+n, depth+1);
82                         }
83                         return;
84                 } else {
85 #if 0
86                         print_depth(depth);
87                         printf("expand by %d gives fault 0x%x\n", n, p->last_fault_code);
88 #endif
89                 }
90                 if (p->last_fault_code == 5) {
91                         reopen(&p, iface);
92                 }
93         }
94
95         dcerpc_pipe_close(p);   
96 }
97
98
99 static void test_ptr_scan(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, 
100                           int opnum, DATA_BLOB *base_in, int min_ofs, int max_ofs, int depth)
101 {
102         DATA_BLOB stub_in, stub_out;
103         int ofs;
104         NTSTATUS status;
105         struct dcerpc_pipe *p = NULL;
106
107         reopen(&p, iface);
108
109         stub_in = data_blob(NULL, base_in->length);
110         memcpy(stub_in.data, base_in->data, base_in->length);
111
112         /* work out which elements are pointers */
113         for (ofs=min_ofs;ofs<=max_ofs-4;ofs+=4) {
114                 SIVAL(stub_in.data, ofs, 1);
115                 status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
116
117                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
118                         print_depth(depth);
119                         printf("possible ptr at ofs %d - fault 0x%08x\n", 
120                                ofs-min_ofs, p->last_fault_code);
121                         if (p->last_fault_code == 5) {
122                                 reopen(&p, iface);
123                         }
124                         if (depth == 0) {
125                                 try_expand(mem_ctx, iface, opnum, &stub_in, ofs+4, depth+1);
126                         } else {
127                                 try_expand(mem_ctx, iface, opnum, &stub_in, max_ofs, depth+1);
128                         }
129                         SIVAL(stub_in.data, ofs, 0);
130                         continue;
131                 }
132                 SIVAL(stub_in.data, ofs, 0);
133         }
134
135         dcerpc_pipe_close(p);   
136 }
137         
138
139 static void test_scan_call(TALLOC_CTX *mem_ctx, const struct dcerpc_interface_table *iface, int opnum)
140 {
141         DATA_BLOB stub_in, stub_out;
142         int i;
143         NTSTATUS status;
144         struct dcerpc_pipe *p = NULL;
145
146         reopen(&p, iface);
147
148         /* work out the minimum amount of input data */
149         for (i=0;i<2000;i++) {
150                 stub_in = data_blob(NULL, i);
151                 data_blob_clear(&stub_in);
152
153
154                 status = dcerpc_request(p, opnum, mem_ctx, &stub_in, &stub_out);
155
156                 if (NT_STATUS_IS_OK(status)) {
157                         printf("opnum %d   min_input %d - output %d\n", 
158                                opnum, stub_in.length, stub_out.length);
159                         dump_data(0, stub_out.data, stub_out.length);
160                         dcerpc_pipe_close(p);
161                         test_ptr_scan(mem_ctx, iface, opnum, &stub_in, 0, stub_in.length, 0);
162                         return;
163                 }
164
165                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
166                         printf("opnum %d  size %d fault 0x%08x\n", opnum, i, p->last_fault_code);
167                         if (p->last_fault_code == 5) {
168                                 reopen(&p, iface);
169                         }
170                         continue;
171                 }
172
173                 printf("opnum %d  size %d error %s\n", opnum, i, nt_errstr(status));
174         }
175
176         printf("opnum %d minimum not found!?\n", opnum);
177         dcerpc_pipe_close(p);
178 }
179
180
181 static BOOL test_scan(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
182 {
183         test_scan_call(mem_ctx, &dcerpc_table_drsuapi, 0x0);
184         return True;
185 }
186 #endif
187
188 static BOOL test_DRSBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
189 {
190         NTSTATUS status;
191         struct DRSUAPI_BIND r;
192         BOOL ret = True;
193
194         ZERO_STRUCT(r.in.blob);
195
196         status = dcerpc_DRSUAPI_BIND(p, mem_ctx, &r);
197         if (!NT_STATUS_IS_OK(status)) {
198                 const char *errstr = nt_errstr(status);
199                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
200                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
201                 }
202                 printf("DRSUAPI_BIND level failed - %s\n", errstr);
203                 ret = False;
204         }
205
206         return ret;
207 }
208
209 BOOL torture_rpc_drsuapi(int dummy)
210 {
211         NTSTATUS status;
212         struct dcerpc_pipe *p;
213         TALLOC_CTX *mem_ctx;
214         BOOL ret = True;
215         void *join_ctx;
216         const char *binding = lp_parm_string(-1, "torture", "binding");
217
218         if (!binding) {
219                 printf("You must specify a ncacn binding string\n");
220                 return False;
221         }
222
223         lp_set_cmdline("netbios name", TEST_MACHINE_NAME);
224
225         join_ctx = torture_join_domain(TEST_MACHINE_NAME, lp_workgroup(), ACB_SVRTRUST, 
226                                        &machine_password);
227         if (!join_ctx) {
228                 printf("Failed to join as BDC\n");
229                 return False;
230         }
231
232         status = dcerpc_pipe_connect(&p, binding,
233                                         DCERPC_DRSUAPI_UUID,
234                                         DCERPC_DRSUAPI_VERSION,
235                                         lp_workgroup(), 
236                                         TEST_MACHINE_NAME"$",
237                                         machine_password);
238
239         if (!NT_STATUS_IS_OK(status)) {
240                 return False;
241         }
242
243         mem_ctx = talloc_init("torture_rpc_drsuapi");
244
245         if (!test_DRSBind(p, mem_ctx)) {
246                 ret = False;
247         }
248
249 #if 0
250         if (!test_scan(p, mem_ctx)) {
251                 ret = False;
252         }
253 #endif
254         talloc_destroy(mem_ctx);
255
256         torture_rpc_close(p);
257
258         torture_leave_domain(join_ctx);
259
260         return ret;
261 }