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