379cca19bec571f913996b7ed1e89164fd480158
[jelmer/samba4-debian.git] / source / torture / libnet / libnet_domain.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Test suite for libnet calls.
4
5    Copyright (C) Rafal Szczesniak 2006
6    
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 3 of the License, or
10    (at your option) any later version.
11    
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.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22 #include "includes.h"
23 #include "lib/cmdline/popt_common.h"
24 #include "lib/events/events.h"
25 #include "auth/credentials/credentials.h"
26 #include "libnet/libnet.h"
27 #include "librpc/gen_ndr/ndr_samr_c.h"
28 #include "librpc/gen_ndr/ndr_lsa_c.h"
29 #include "libcli/security/security.h"
30 #include "librpc/rpc/dcerpc.h"
31 #include "torture/torture.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
34
35
36 static bool test_opendomain_samr(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
37                                  struct policy_handle *handle, struct lsa_String *domname,
38                                  uint32_t *access_mask, struct dom_sid **sid)
39 {
40         NTSTATUS status;
41         struct policy_handle h, domain_handle;
42         struct samr_Connect r1;
43         struct samr_LookupDomain r2;
44         struct samr_OpenDomain r3;
45         
46         printf("connecting\n");
47
48         *access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
49         
50         r1.in.system_name = 0;
51         r1.in.access_mask = *access_mask;
52         r1.out.connect_handle = &h;
53         
54         status = dcerpc_samr_Connect(p, mem_ctx, &r1);
55         if (!NT_STATUS_IS_OK(status)) {
56                 printf("Connect failed - %s\n", nt_errstr(status));
57                 return false;
58         }
59         
60         r2.in.connect_handle = &h;
61         r2.in.domain_name = domname;
62
63         printf("domain lookup on %s\n", domname->string);
64
65         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r2);
66         if (!NT_STATUS_IS_OK(status)) {
67                 printf("LookupDomain failed - %s\n", nt_errstr(status));
68                 return false;
69         }
70
71         r3.in.connect_handle = &h;
72         r3.in.access_mask = *access_mask;
73         r3.in.sid = *sid = r2.out.sid;
74         r3.out.domain_handle = &domain_handle;
75
76         printf("opening domain\n");
77
78         status = dcerpc_samr_OpenDomain(p, mem_ctx, &r3);
79         if (!NT_STATUS_IS_OK(status)) {
80                 printf("OpenDomain failed - %s\n", nt_errstr(status));
81                 return false;
82         } else {
83                 *handle = domain_handle;
84         }
85
86         return true;
87 }
88
89
90 static bool test_opendomain_lsa(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
91                                 struct policy_handle *handle, struct lsa_String *domname,
92                                 uint32_t *access_mask)
93 {
94         NTSTATUS status;
95         struct lsa_OpenPolicy2 open;
96         struct lsa_ObjectAttribute attr;
97         struct lsa_QosInfo qos;
98
99         *access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
100
101         ZERO_STRUCT(attr);
102         ZERO_STRUCT(qos);
103
104         qos.len                 = 0;
105         qos.impersonation_level = 2;
106         qos.context_mode        = 1;
107         qos.effective_only      = 0;
108         
109         attr.sec_qos = &qos;
110
111         open.in.system_name = domname->string;
112         open.in.attr        = &attr;
113         open.in.access_mask = *access_mask;
114         open.out.handle     = handle;
115         
116         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &open);
117         if (!NT_STATUS_IS_OK(status)) {
118                 return false;
119         }
120
121         return true;
122 }
123
124 bool torture_domain_open_lsa(struct torture_context *torture)
125 {
126         NTSTATUS status;
127         bool ret = true;
128         struct libnet_context *ctx;
129         struct libnet_DomainOpen r;
130         struct lsa_Close lsa_close;
131         struct policy_handle h;
132         const char *domain_name;
133
134         /* we're accessing domain controller so the domain name should be
135            passed (it's going to be resolved to dc name and address) instead
136            of specific server name. */
137         domain_name = lp_workgroup(global_loadparm);
138
139         ctx = libnet_context_init(NULL);
140         if (ctx == NULL) {
141                 d_printf("failed to create libnet context\n");
142                 return false;
143         }
144
145         ctx->cred = cmdline_credentials;
146
147         ZERO_STRUCT(r);
148         r.in.type = DOMAIN_LSA;
149         r.in.domain_name = domain_name;
150         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
151
152         status = libnet_DomainOpen(ctx, torture, &r);
153         if (!NT_STATUS_IS_OK(status)) {
154                 d_printf("failed to open domain on lsa service: %s\n", nt_errstr(status));
155                 ret = false;
156                 goto done;
157         }
158
159         ZERO_STRUCT(lsa_close);
160         lsa_close.in.handle  = &ctx->lsa.handle;
161         lsa_close.out.handle = &h;
162         
163         status = dcerpc_lsa_Close(ctx->lsa.pipe, ctx, &lsa_close);
164         if (!NT_STATUS_IS_OK(status)) {
165                 d_printf("failed to close domain on lsa service: %s\n", nt_errstr(status));
166                 ret = false;
167         }
168
169 done:
170         talloc_free(ctx);
171         return ret;
172 }
173
174
175 bool torture_domain_close_lsa(struct torture_context *torture)
176 {
177         bool ret = true;
178         NTSTATUS status;
179         TALLOC_CTX *mem_ctx=NULL;
180         struct libnet_context *ctx;
181         struct lsa_String domain_name;
182         struct dcerpc_binding *binding;
183         uint32_t access_mask;
184         struct policy_handle h;
185         struct dcerpc_pipe *p;
186         struct libnet_DomainClose r;
187
188         status = torture_rpc_binding(torture, &binding);
189         if (!NT_STATUS_IS_OK(status)) {
190                 return false;
191         }
192
193         ctx = libnet_context_init(NULL);
194         if (ctx == NULL) {
195                 d_printf("failed to create libnet context\n");
196                 ret = false;
197                 goto done;
198         }
199
200         ctx->cred = cmdline_credentials;
201
202         mem_ctx = talloc_init("torture_domain_close_lsa");
203         status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_lsarpc,
204                                      cmdline_credentials, NULL);
205         if (!NT_STATUS_IS_OK(status)) {
206                 d_printf("failed to connect to server: %s\n", nt_errstr(status));
207                 ret = false;
208                 goto done;
209         }
210
211         domain_name.string = lp_workgroup(global_loadparm);
212         
213         if (!test_opendomain_lsa(p, torture, &h, &domain_name, &access_mask)) {
214                 d_printf("failed to open domain on lsa service\n");
215                 ret = false;
216                 goto done;
217         }
218         
219         ctx->lsa.pipe        = p;
220         ctx->lsa.name        = domain_name.string;
221         ctx->lsa.access_mask = access_mask;
222         ctx->lsa.handle      = h;
223         /* we have to use pipe's event context, otherwise the call will
224            hang indefinitely */
225         ctx->event_ctx       = p->conn->event_ctx;
226
227         ZERO_STRUCT(r);
228         r.in.type = DOMAIN_LSA;
229         r.in.domain_name = domain_name.string;
230         
231         status = libnet_DomainClose(ctx, mem_ctx, &r);
232         if (!NT_STATUS_IS_OK(status)) {
233                 ret = false;
234                 goto done;
235         }
236
237 done:
238         talloc_free(mem_ctx);
239         talloc_free(ctx);
240         return ret;
241 }
242
243
244 bool torture_domain_open_samr(struct torture_context *torture)
245 {
246         NTSTATUS status;
247         struct libnet_context *ctx;
248         struct event_context *evt_ctx=NULL;
249         TALLOC_CTX *mem_ctx;
250         struct policy_handle domain_handle, handle;
251         struct libnet_DomainOpen io;
252         struct samr_Close r;
253         const char *domain_name;
254         bool ret = true;
255
256         mem_ctx = talloc_init("test_domainopen_lsa");
257
258         ctx = libnet_context_init(evt_ctx);
259         ctx->cred = cmdline_credentials;
260
261         /* we're accessing domain controller so the domain name should be
262            passed (it's going to be resolved to dc name and address) instead
263            of specific server name. */
264         domain_name = lp_workgroup(global_loadparm);
265
266         /*
267          * Testing synchronous version
268          */
269         printf("opening domain\n");
270         
271         io.in.type         = DOMAIN_SAMR;
272         io.in.domain_name  = domain_name;
273         io.in.access_mask  = SEC_FLAG_MAXIMUM_ALLOWED;
274
275         status = libnet_DomainOpen(ctx, mem_ctx, &io);
276         if (!NT_STATUS_IS_OK(status)) {
277                 printf("Composite domain open failed - %s\n", nt_errstr(status));
278                 ret = false;
279                 goto done;
280         }
281
282         domain_handle = ctx->samr.handle;
283
284         r.in.handle   = &domain_handle;
285         r.out.handle  = &handle;
286         
287         printf("closing domain handle\n");
288         
289         status = dcerpc_samr_Close(ctx->samr.pipe, mem_ctx, &r);
290         if (!NT_STATUS_IS_OK(status)) {
291                 printf("Close failed - %s\n", nt_errstr(status));
292                 ret = false;
293                 goto done;
294         }
295
296 done:
297         talloc_free(mem_ctx);
298         talloc_free(ctx);
299
300         return ret;
301 }
302
303
304 bool torture_domain_close_samr(struct torture_context *torture)
305 {
306         bool ret = true;
307         NTSTATUS status;
308         TALLOC_CTX *mem_ctx = NULL;
309         struct libnet_context *ctx;
310         struct lsa_String domain_name;
311         struct dcerpc_binding *binding;
312         uint32_t access_mask;
313         struct policy_handle h;
314         struct dcerpc_pipe *p;
315         struct libnet_DomainClose r;
316         struct dom_sid *sid;
317
318         status = torture_rpc_binding(torture, &binding);
319         if (!NT_STATUS_IS_OK(status)) {
320                 return false;
321         }
322
323         ctx = libnet_context_init(NULL);
324         if (ctx == NULL) {
325                 d_printf("failed to create libnet context\n");
326                 ret = false;
327                 goto done;
328         }
329
330         ctx->cred = cmdline_credentials;
331
332         mem_ctx = talloc_init("torture_domain_close_samr");
333         status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_samr,
334                                      ctx->cred, NULL);
335         if (!NT_STATUS_IS_OK(status)) {
336                 d_printf("failed to connect to server: %s\n", nt_errstr(status));
337                 ret = false;
338                 goto done;
339         }
340
341         domain_name.string = talloc_strdup(mem_ctx, lp_workgroup(global_loadparm));
342         
343         if (!test_opendomain_samr(p, torture, &h, &domain_name, &access_mask, &sid)) {
344                 d_printf("failed to open domain on samr service\n");
345                 ret = false;
346                 goto done;
347         }
348         
349         ctx->samr.pipe        = p;
350         ctx->samr.name        = talloc_steal(ctx, domain_name.string);
351         ctx->samr.access_mask = access_mask;
352         ctx->samr.handle      = h;
353         ctx->samr.sid         = talloc_steal(ctx, sid);
354         /* we have to use pipe's event context, otherwise the call will
355            hang indefinitely - this wouldn't be the case if pipe was opened
356            by means of libnet call */
357         ctx->event_ctx       = p->conn->event_ctx;
358
359         ZERO_STRUCT(r);
360         r.in.type = DOMAIN_SAMR;
361         r.in.domain_name = domain_name.string;
362         
363         status = libnet_DomainClose(ctx, mem_ctx, &r);
364         if (!NT_STATUS_IS_OK(status)) {
365                 ret = false;
366                 goto done;
367         }
368
369 done:
370         talloc_free(mem_ctx);
371         talloc_free(ctx);
372         return ret;
373 }
374
375
376 bool torture_domain_list(struct torture_context *torture)
377 {
378         bool ret = true;
379         NTSTATUS status;
380         TALLOC_CTX *mem_ctx = NULL;
381         struct dcerpc_binding *binding;
382         struct libnet_context *ctx;
383         struct libnet_DomainList r;
384         int i;
385
386         status = torture_rpc_binding(torture, &binding);
387         if (!NT_STATUS_IS_OK(status)) {
388                 return false;
389         }
390
391         ctx = libnet_context_init(NULL);
392         if (ctx == NULL) {
393                 d_printf("failed to create libnet context\n");
394                 ret = false;
395                 goto done;
396         }
397
398         ctx->cred = cmdline_credentials;
399         
400         mem_ctx = talloc_init("torture_domain_close_samr");
401
402         /*
403          * querying the domain list using default buffer size
404          */
405
406         ZERO_STRUCT(r);
407         r.in.hostname = binding->host;
408
409         status = libnet_DomainList(ctx, mem_ctx, &r);
410         if (!NT_STATUS_IS_OK(status)) {
411                 ret = false;
412                 goto done;
413         }
414
415         d_printf("Received list or domains (everything in one piece):\n");
416         
417         for (i = 0; i < r.out.count; i++) {
418                 d_printf("Name[%d]: %s\n", i, r.out.domains[i].name);
419         }
420
421         /*
422          * querying the domain list using specified (much smaller) buffer size
423          */
424
425         ctx->samr.buf_size = 32;
426
427         ZERO_STRUCT(r);
428         r.in.hostname = binding->host;
429
430         status = libnet_DomainList(ctx, mem_ctx, &r);
431         if (!NT_STATUS_IS_OK(status)) {
432                 ret = false;
433                 goto done;
434         }
435
436         d_printf("Received list or domains (collected in more than one round):\n");
437         
438         for (i = 0; i < r.out.count; i++) {
439                 d_printf("Name[%d]: %s\n", i, r.out.domains[i].name);
440         }
441
442 done:
443         d_printf("\nStatus: %s\n", nt_errstr(status));
444
445         talloc_free(mem_ctx);
446         talloc_free(ctx);
447         return ret;
448 }