* fixed conformant arrays in structures
[samba.git] / source4 / torture / rpc / lsa.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for lsa rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24
25 /*
26   these really shouldn't be here ....
27 */
28 static char *lsa_sid_string_talloc(TALLOC_CTX *mem_ctx, struct dom_sid *sid)
29 {
30         int i, ofs, maxlen;
31         uint32 ia;
32         char *ret;
33         
34         if (!sid) {
35                 return talloc_asprintf(mem_ctx, "(NULL SID)");
36         }
37
38         maxlen = sid->num_auths * 11 + 25;
39         ret = talloc(mem_ctx, maxlen);
40         if (!ret) return NULL;
41
42         ia = (sid->id_auth[5]) +
43                 (sid->id_auth[4] << 8 ) +
44                 (sid->id_auth[3] << 16) +
45                 (sid->id_auth[2] << 24);
46
47         ofs = snprintf(ret, maxlen, "S-%u-%lu", 
48                        (unsigned int)sid->sid_rev_num, (unsigned long)ia);
49
50         for (i = 0; i < sid->num_auths; i++) {
51                 ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]);
52         }
53
54         return ret;
55 }
56
57 static int dom_sid_compare(struct dom_sid *sid1, struct dom_sid *sid2)
58 {
59         int i;
60
61         if (sid1 == sid2) return 0;
62         if (!sid1) return -1;
63         if (!sid2) return 1;
64
65         /* Compare most likely different rids, first: i.e start at end */
66         if (sid1->num_auths != sid2->num_auths)
67                 return sid1->num_auths - sid2->num_auths;
68
69         for (i = sid1->num_auths-1; i >= 0; --i)
70                 if (sid1->sub_auths[i] != sid2->sub_auths[i])
71                         return sid1->sub_auths[i] - sid2->sub_auths[i];
72
73         if (sid1->sid_rev_num != sid2->sid_rev_num)
74                 return sid1->sid_rev_num - sid2->sid_rev_num;
75
76         for (i = 0; i < 6; i++)
77                 if (sid1->id_auth[i] != sid2->id_auth[i])
78                         return sid1->id_auth[i] - sid2->id_auth[i];
79
80         return 0;
81 }
82
83 static BOOL test_OpenPolicy(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
84 {
85         struct lsa_ObjectAttribute attr;
86         struct policy_handle handle;
87         struct lsa_QosInfo qos;
88         struct lsa_OpenPolicy r;
89         NTSTATUS status;
90         uint16 system_name = '\\';
91
92         printf("\ntesting OpenPolicy\n");
93
94         qos.impersonation_level = 2;
95         qos.context_mode = 1;
96         qos.effective_only = 0;
97
98         attr.root_dir = NULL;
99         attr.object_name = NULL;
100         attr.attributes = 0;
101         attr.sec_desc = NULL;
102         attr.sec_qos = &qos;
103
104         r.in.system_name = &system_name;
105         r.in.attr = &attr;
106         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
107         r.out.handle = &handle;
108
109         status = dcerpc_lsa_OpenPolicy(p, mem_ctx, &r);
110         if (!NT_STATUS_IS_OK(status)) {
111                 printf("OpenPolicy failed - %s\n", nt_errstr(status));
112                 return False;
113         }
114
115         return True;
116 }
117
118
119 static BOOL test_OpenPolicy2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
120                              struct policy_handle *handle)
121 {
122         struct lsa_ObjectAttribute attr;
123         struct lsa_QosInfo qos;
124         struct lsa_OpenPolicy2 r;
125         NTSTATUS status;
126
127         printf("\ntesting OpenPolicy2\n");
128
129         qos.impersonation_level = 2;
130         qos.context_mode = 1;
131         qos.effective_only = 0;
132
133         attr.root_dir = NULL;
134         attr.object_name = NULL;
135         attr.attributes = 0;
136         attr.sec_desc = NULL;
137         attr.sec_qos = &qos;
138
139         r.in.system_name = "\\";
140         r.in.attr = &attr;
141         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
142         r.out.handle = handle;
143
144         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r);
145         if (!NT_STATUS_IS_OK(status)) {
146                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
147                 return False;
148         }
149
150         return True;
151 }
152
153 static BOOL test_LookupNames(struct dcerpc_pipe *p, 
154                             TALLOC_CTX *mem_ctx, 
155                             struct policy_handle *handle,
156                             struct lsa_TransNameArray *tnames)
157 {
158         struct lsa_LookupNames r;
159         struct lsa_TransSidArray sids;
160         struct lsa_Name *names;
161         uint32 count = 0;
162         NTSTATUS status;
163         int i;
164
165         printf("\nTesting LookupNames\n");
166
167         sids.count = 0;
168         sids.sids = NULL;
169
170         names = talloc(mem_ctx, tnames->count * sizeof(names[0]));
171         for (i=0;i<tnames->count;i++) {
172                 names[i].name_len = 2*strlen(tnames->names[i].name.name);
173                 names[i].name_size = 2*strlen(tnames->names[i].name.name);
174                 names[i].name = tnames->names[i].name.name;
175         }
176
177         r.in.handle = handle;
178         r.in.num_names = tnames->count;
179         r.in.names = names;
180         r.in.sids = &sids;
181         r.in.level = 1;
182         r.in.count = &count;
183         r.out.count = &count;
184         r.out.sids = &sids;
185
186         status = dcerpc_lsa_LookupNames(p, mem_ctx, &r);
187         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
188                 printf("LookupNames failed - %s\n", nt_errstr(status));
189                 return False;
190         }
191
192         if (r.out.domains) {
193                 NDR_PRINT_DEBUG(lsa_RefDomainList, r.out.domains);
194         }
195
196         printf("lookup gave %d sids (sids.count=%d)\n", count, sids.count);
197
198         NDR_PRINT_DEBUG(lsa_TransSidArray, r.out.sids);
199
200         printf("\n");
201
202         return True;
203 }
204
205
206 static BOOL test_LookupSids(struct dcerpc_pipe *p, 
207                             TALLOC_CTX *mem_ctx, 
208                             struct policy_handle *handle,
209                             struct lsa_SidArray *sids)
210 {
211         struct lsa_LookupSids r;
212         struct lsa_TransNameArray names;
213         uint32 count = sids->num_sids;
214         NTSTATUS status;
215
216         printf("\nTesting LookupSids\n");
217
218         names.count = 0;
219         names.names = NULL;
220
221         r.in.handle = handle;
222         r.in.sids = sids;
223         r.in.names = &names;
224         r.in.level = 1;
225         r.in.count = &count;
226         r.out.count = &count;
227         r.out.names = &names;
228
229         status = dcerpc_lsa_LookupSids(p, mem_ctx, &r);
230         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
231                 printf("LookupSids failed - %s\n", nt_errstr(status));
232                 return False;
233         }
234
235         if (r.out.domains) {
236                 NDR_PRINT_DEBUG(lsa_RefDomainList, r.out.domains);
237         }
238
239         NDR_PRINT_DEBUG(lsa_TransNameArray, r.out.names);
240
241         printf("\n");
242
243         if (!test_LookupNames(p, mem_ctx, handle, &names)) {
244                 return False;
245         }
246
247         return True;
248 }
249
250 static BOOL test_LookupPrivName(struct dcerpc_pipe *p, 
251                                 TALLOC_CTX *mem_ctx, 
252                                 struct policy_handle *handle,
253                                 struct lsa_LUID *luid)
254 {
255         NTSTATUS status;
256         struct lsa_LookupPrivName r;
257
258         r.in.handle = handle;
259         r.in.luid_high = luid->high;
260         r.in.luid_low = luid->low;
261
262         status = dcerpc_lsa_LookupPrivName(p, mem_ctx, &r);
263         if (!NT_STATUS_IS_OK(status)) {
264                 printf("\nLookupPrivName failed - %s\n", nt_errstr(status));
265                 return False;
266         }
267
268         NDR_PRINT_DEBUG(lsa_Name, r.out.name);
269
270         return True;
271 }
272
273 static BOOL test_EnumPrivsAccount(struct dcerpc_pipe *p, 
274                                   TALLOC_CTX *mem_ctx,                            
275                                   struct policy_handle *handle,
276                                   struct policy_handle *acct_handle)
277 {
278         NTSTATUS status;
279         struct lsa_EnumPrivsAccount r;
280
281         printf("Testing EnumPrivsAccount\n");
282
283         r.in.handle = acct_handle;
284
285         status = dcerpc_lsa_EnumPrivsAccount(p, mem_ctx, &r);
286         if (!NT_STATUS_IS_OK(status)) {
287                 printf("EnumPrivsAccount failed - %s\n", nt_errstr(status));
288                 return False;
289         }
290
291         printf("received %d privileges\n", 
292                r.out.privs?r.out.privs->count:0);
293
294         if (r.out.privs) {
295                 int i;
296                 NDR_PRINT_DEBUG(lsa_PrivilegeSet, r.out.privs);
297                 for (i=0;i<r.out.privs->count;i++) {
298                         test_LookupPrivName(p, mem_ctx, handle, 
299                                             &r.out.privs->set[i].luid);
300                 }
301         }
302
303         return True;
304 }
305
306 static BOOL test_EnumAccountRights(struct dcerpc_pipe *p, 
307                                    TALLOC_CTX *mem_ctx, 
308                                    struct policy_handle *acct_handle,
309                                    struct dom_sid *sid)
310 {
311         NTSTATUS status;
312         struct lsa_EnumAccountRights r;
313         struct lsa_RightSet rights;
314
315         printf("Testing EnumAccountRights\n");
316
317         r.in.handle = acct_handle;
318         r.in.sid = sid;
319         r.out.rights = &rights;
320
321         status = dcerpc_lsa_EnumAccountRights(p, mem_ctx, &r);
322         if (!NT_STATUS_IS_OK(status)) {
323                 printf("EnumAccountRights failed - %s\n", nt_errstr(status));
324                 return False;
325         }
326
327         NDR_PRINT_DEBUG(lsa_RightSet, r.out.rights);
328
329         return True;
330 }
331
332 static BOOL test_OpenAccount(struct dcerpc_pipe *p, 
333                              TALLOC_CTX *mem_ctx, 
334                              struct policy_handle *handle,
335                              struct dom_sid *sid)
336 {
337         NTSTATUS status;
338         struct lsa_OpenAccount r;
339         struct policy_handle acct_handle;
340
341         printf("Testing OpenAccount(%s)\n", lsa_sid_string_talloc(mem_ctx, sid));
342
343         r.in.handle = handle;
344         r.in.sid = sid;
345         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
346         r.out.acct_handle = &acct_handle;
347
348         status = dcerpc_lsa_OpenAccount(p, mem_ctx, &r);
349         if (!NT_STATUS_IS_OK(status)) {
350                 printf("OpenAccount failed - %s\n", nt_errstr(status));
351                 return False;
352         }
353
354         if (!test_EnumPrivsAccount(p, mem_ctx, handle, &acct_handle)) {
355                 return False;
356         }
357
358         return True;
359 }
360
361 static BOOL test_EnumAccounts(struct dcerpc_pipe *p, 
362                           TALLOC_CTX *mem_ctx, 
363                           struct policy_handle *handle)
364 {
365         NTSTATUS status;
366         struct lsa_EnumAccounts r;
367         struct lsa_SidArray sids1, sids2;
368         uint32 resume_handle = 0;
369         int i;
370
371         printf("\ntesting EnumAccounts\n");
372
373         r.in.handle = handle;
374         r.in.resume_handle = &resume_handle;
375         r.in.num_entries = 100;
376         r.out.resume_handle = &resume_handle;
377         r.out.sids = &sids1;
378
379         resume_handle = 0;
380         status = dcerpc_lsa_EnumAccounts(p, mem_ctx, &r);
381         if (!NT_STATUS_IS_OK(status)) {
382                 printf("EnumAccounts failed - %s\n", nt_errstr(status));
383                 return False;
384         }
385
386         printf("Got %d sids resume_handle=%u\n", sids1.num_sids, resume_handle);
387
388         NDR_PRINT_DEBUG(lsa_SidArray, r.out.sids);
389
390         if (!test_LookupSids(p, mem_ctx, handle, &sids1)) {
391                 return False;
392         }
393
394         printf("testing all accounts\n");
395         for (i=0;i<sids1.num_sids;i++) {
396                 test_OpenAccount(p, mem_ctx, handle, sids1.sids[i].sid);
397                 test_EnumAccountRights(p, mem_ctx, handle, sids1.sids[i].sid);
398         }
399         printf("\n");
400
401         if (sids1.num_sids < 3) {
402                 return True;
403         }
404         
405         printf("trying EnumAccounts partial listing (asking for 1 at 2)\n");
406         resume_handle = 2;
407         r.in.num_entries = 1;
408         r.out.sids = &sids2;
409
410         status = dcerpc_lsa_EnumAccounts(p, mem_ctx, &r);
411         if (!NT_STATUS_IS_OK(status)) {
412                 printf("EnumAccounts failed - %s\n", nt_errstr(status));
413                 return False;
414         }
415
416         NDR_PRINT_DEBUG(lsa_SidArray, r.out.sids);
417
418         if (sids2.num_sids != 1) {
419                 printf("Returned wrong number of entries (%d)\n", sids2.num_sids);
420                 return False;
421         }
422
423         return True;
424 }
425
426
427 static BOOL test_EnumPrivs(struct dcerpc_pipe *p, 
428                            TALLOC_CTX *mem_ctx, 
429                            struct policy_handle *handle)
430 {
431         NTSTATUS status;
432         struct lsa_EnumPrivs r;
433         struct lsa_PrivArray privs1;
434         uint32 resume_handle = 0;
435
436         printf("\ntesting EnumPrivs\n");
437
438         r.in.handle = handle;
439         r.in.resume_handle = &resume_handle;
440         r.in.max_count = 1000;
441         r.out.resume_handle = &resume_handle;
442         r.out.privs = &privs1;
443
444         resume_handle = 0;
445         status = dcerpc_lsa_EnumPrivs(p, mem_ctx, &r);
446         if (!NT_STATUS_IS_OK(status)) {
447                 printf("EnumPrivs failed - %s\n", nt_errstr(status));
448                 return False;
449         }
450
451         printf("Got %d privs resume_handle=%u\n", privs1.count, resume_handle);
452
453         NDR_PRINT_DEBUG(lsa_PrivArray, r.out.privs);
454
455         return True;
456 }
457
458
459 static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, 
460                               TALLOC_CTX *mem_ctx, 
461                               struct policy_handle *handle)
462 {
463         struct lsa_EnumTrustDom r;
464         NTSTATUS status;
465         uint32 resume_handle = 0;
466         struct lsa_DomainList domains;
467
468         printf("\nTesting EnumTrustDom\n");
469
470         r.in.handle = handle;
471         r.in.resume_handle = &resume_handle;
472         r.in.num_entries = 1000;
473         r.out.domains = &domains;
474         r.out.resume_handle = &resume_handle;
475
476         status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
477         if (!NT_STATUS_IS_OK(status)) {
478                 printf("EnumTrustDom failed - %s\n", nt_errstr(status));
479                 return False;
480         }
481
482         printf("lookup gave %d domains\n", domains.count);
483
484         NDR_PRINT_DEBUG(lsa_DomainList, r.out.domains);
485
486         return True;
487 }
488
489 static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p, 
490                                  TALLOC_CTX *mem_ctx, 
491                                  struct policy_handle *handle)
492 {
493         struct lsa_QueryInfoPolicy r;
494         NTSTATUS status;
495         int i;
496         BOOL ret = True;
497
498         printf("\nTesting QueryInfoPolicy\n");
499
500         for (i=1;i<13;i++) {
501                 r.in.handle = handle;
502                 r.in.level = i;
503
504                 printf("\ntrying QueryInfoPolicy level %d\n", i);
505
506                 status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
507                 if (!NT_STATUS_IS_OK(status)) {
508                         printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
509                         ret = False;
510                         continue;
511                 }
512
513                 NDR_PRINT_UNION_DEBUG(lsa_PolicyInformation, r.in.level, r.out.info);
514         }
515
516         return ret;
517 }
518
519 static BOOL test_Delete(struct dcerpc_pipe *p, 
520                        TALLOC_CTX *mem_ctx, 
521                        struct policy_handle *handle)
522 {
523         NTSTATUS status;
524         struct lsa_Delete r;
525
526         printf("\ntesting Delete - but what does it do?\n");
527
528         r.in.handle = handle;
529         status = dcerpc_lsa_Delete(p, mem_ctx, &r);
530         if (!NT_STATUS_IS_OK(status)) {
531                 printf("Delete failed - %s\n", nt_errstr(status));
532                 return False;
533         }
534
535         printf("\n");
536
537         return True;
538 }
539
540 static BOOL test_Close(struct dcerpc_pipe *p, 
541                        TALLOC_CTX *mem_ctx, 
542                        struct policy_handle *handle)
543 {
544         NTSTATUS status;
545         struct lsa_Close r;
546         struct policy_handle handle2;
547
548         printf("\ntesting Close\n");
549
550         r.in.handle = handle;
551         r.out.handle = &handle2;
552
553         status = dcerpc_lsa_Close(p, mem_ctx, &r);
554         if (!NT_STATUS_IS_OK(status)) {
555                 printf("Close failed - %s\n", nt_errstr(status));
556                 return False;
557         }
558
559         status = dcerpc_lsa_Close(p, mem_ctx, &r);
560         /* its really a fault - we need a status code for rpc fault */
561         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
562                 printf("Close failed - %s\n", nt_errstr(status));
563                 return False;
564         }
565
566         printf("\n");
567
568         return True;
569 }
570
571 BOOL torture_rpc_lsa(int dummy)
572 {
573         NTSTATUS status;
574         struct dcerpc_pipe *p;
575         TALLOC_CTX *mem_ctx;
576         BOOL ret = True;
577         struct policy_handle handle;
578
579         mem_ctx = talloc_init("torture_rpc_lsa");
580
581         status = torture_rpc_connection(&p, "lsarpc");
582         if (!NT_STATUS_IS_OK(status)) {
583                 return False;
584         }
585         
586         if (!test_OpenPolicy(p, mem_ctx)) {
587                 ret = False;
588         }
589
590         if (!test_OpenPolicy2(p, mem_ctx, &handle)) {
591                 ret = False;
592         }
593
594         if (!test_EnumAccounts(p, mem_ctx, &handle)) {
595                 ret = False;
596         }
597
598         if (!test_EnumPrivs(p, mem_ctx, &handle)) {
599                 ret = False;
600         }
601
602         if (!test_EnumTrustDom(p, mem_ctx, &handle)) {
603                 ret = False;
604         }
605
606         if (!test_QueryInfoPolicy(p, mem_ctx, &handle)) {
607                 ret = False;
608         }
609         
610 #if 0
611         if (!test_Delete(p, mem_ctx, &handle)) {
612                 ret = False;
613         }
614 #endif
615         
616         if (!test_Close(p, mem_ctx, &handle)) {
617                 ret = False;
618         }
619
620         torture_rpc_close(p);
621
622         return ret;
623 }