added lsa_QuerySecObj() and the necessary sec_desc_buf supporting code
[sfrench/samba-autobuild/.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.len = 0;
95         qos.impersonation_level = 2;
96         qos.context_mode = 1;
97         qos.effective_only = 0;
98
99         attr.len = 0;
100         attr.root_dir = NULL;
101         attr.object_name = NULL;
102         attr.attributes = 0;
103         attr.sec_desc = NULL;
104         attr.sec_qos = &qos;
105
106         r.in.system_name = &system_name;
107         r.in.attr = &attr;
108         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
109         r.out.handle = &handle;
110
111         status = dcerpc_lsa_OpenPolicy(p, mem_ctx, &r);
112         if (!NT_STATUS_IS_OK(status)) {
113                 printf("OpenPolicy failed - %s\n", nt_errstr(status));
114                 return False;
115         }
116
117         return True;
118 }
119
120
121 static BOOL test_OpenPolicy2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
122                              struct policy_handle *handle)
123 {
124         struct lsa_ObjectAttribute attr;
125         struct lsa_QosInfo qos;
126         struct lsa_OpenPolicy2 r;
127         NTSTATUS status;
128
129         printf("\ntesting OpenPolicy2\n");
130
131         qos.len = 0;
132         qos.impersonation_level = 2;
133         qos.context_mode = 1;
134         qos.effective_only = 0;
135
136         attr.len = 0;
137         attr.root_dir = NULL;
138         attr.object_name = NULL;
139         attr.attributes = 0;
140         attr.sec_desc = NULL;
141         attr.sec_qos = &qos;
142
143         r.in.system_name = "\\";
144         r.in.attr = &attr;
145         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
146         r.out.handle = handle;
147
148         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r);
149         if (!NT_STATUS_IS_OK(status)) {
150                 printf("OpenPolicy2 failed - %s\n", nt_errstr(status));
151                 return False;
152         }
153
154         return True;
155 }
156
157 static BOOL test_LookupNames(struct dcerpc_pipe *p, 
158                             TALLOC_CTX *mem_ctx, 
159                             struct policy_handle *handle,
160                             struct lsa_TransNameArray *tnames)
161 {
162         struct lsa_LookupNames r;
163         struct lsa_TransSidArray sids;
164         struct lsa_Name *names;
165         uint32 count = 0;
166         NTSTATUS status;
167         int i;
168
169         printf("\nTesting LookupNames\n");
170
171         sids.count = 0;
172         sids.sids = NULL;
173
174         names = talloc(mem_ctx, tnames->count * sizeof(names[0]));
175         for (i=0;i<tnames->count;i++) {
176                 names[i].name_len = 2*strlen(tnames->names[i].name.name);
177                 names[i].name_size = 2*strlen(tnames->names[i].name.name);
178                 names[i].name = tnames->names[i].name.name;
179         }
180
181         r.in.handle = handle;
182         r.in.num_names = tnames->count;
183         r.in.names = names;
184         r.in.sids = &sids;
185         r.in.level = 1;
186         r.in.count = &count;
187         r.out.count = &count;
188         r.out.sids = &sids;
189
190         status = dcerpc_lsa_LookupNames(p, mem_ctx, &r);
191         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
192                 printf("LookupNames failed - %s\n", nt_errstr(status));
193                 return False;
194         }
195
196         if (r.out.domains) {
197                 NDR_PRINT_DEBUG(lsa_RefDomainList, r.out.domains);
198         }
199
200         printf("lookup gave %d sids (sids.count=%d)\n", count, sids.count);
201
202         NDR_PRINT_DEBUG(lsa_TransSidArray, r.out.sids);
203
204         printf("\n");
205
206         return True;
207 }
208
209
210 static BOOL test_LookupSids(struct dcerpc_pipe *p, 
211                             TALLOC_CTX *mem_ctx, 
212                             struct policy_handle *handle,
213                             struct lsa_SidArray *sids)
214 {
215         struct lsa_LookupSids r;
216         struct lsa_TransNameArray names;
217         uint32 count = sids->num_sids;
218         NTSTATUS status;
219
220         printf("\nTesting LookupSids\n");
221
222         names.count = 0;
223         names.names = NULL;
224
225         r.in.handle = handle;
226         r.in.sids = sids;
227         r.in.names = &names;
228         r.in.level = 1;
229         r.in.count = &count;
230         r.out.count = &count;
231         r.out.names = &names;
232
233         status = dcerpc_lsa_LookupSids(p, mem_ctx, &r);
234         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
235                 printf("LookupSids failed - %s\n", nt_errstr(status));
236                 return False;
237         }
238
239         if (r.out.domains) {
240                 NDR_PRINT_DEBUG(lsa_RefDomainList, r.out.domains);
241         }
242
243         NDR_PRINT_DEBUG(lsa_TransNameArray, r.out.names);
244
245         printf("\n");
246
247         if (!test_LookupNames(p, mem_ctx, handle, &names)) {
248                 return False;
249         }
250
251         return True;
252 }
253
254 static BOOL test_LookupPrivName(struct dcerpc_pipe *p, 
255                                 TALLOC_CTX *mem_ctx, 
256                                 struct policy_handle *handle,
257                                 struct lsa_LUID *luid)
258 {
259         NTSTATUS status;
260         struct lsa_LookupPrivName r;
261
262         r.in.handle = handle;
263         r.in.luid = luid;
264
265         status = dcerpc_lsa_LookupPrivName(p, mem_ctx, &r);
266         if (!NT_STATUS_IS_OK(status)) {
267                 printf("\nLookupPrivName failed - %s\n", nt_errstr(status));
268                 return False;
269         }
270
271         NDR_PRINT_DEBUG(lsa_Name, r.out.name);
272
273         return True;
274 }
275
276 static BOOL test_EnumPrivsAccount(struct dcerpc_pipe *p, 
277                                   TALLOC_CTX *mem_ctx,                            
278                                   struct policy_handle *handle,
279                                   struct policy_handle *acct_handle)
280 {
281         NTSTATUS status;
282         struct lsa_EnumPrivsAccount r;
283
284         printf("Testing EnumPrivsAccount\n");
285
286         r.in.handle = acct_handle;
287
288         status = dcerpc_lsa_EnumPrivsAccount(p, mem_ctx, &r);
289         if (!NT_STATUS_IS_OK(status)) {
290                 printf("EnumPrivsAccount failed - %s\n", nt_errstr(status));
291                 return False;
292         }
293
294         printf("received %d privileges\n", 
295                r.out.privs?r.out.privs->count:0);
296
297         if (r.out.privs) {
298                 int i;
299                 NDR_PRINT_DEBUG(lsa_PrivilegeSet, r.out.privs);
300                 for (i=0;i<r.out.privs->count;i++) {
301                         test_LookupPrivName(p, mem_ctx, handle, 
302                                             &r.out.privs->set[i].luid);
303                 }
304         }
305
306         return True;
307 }
308
309 static BOOL test_EnumAccountRights(struct dcerpc_pipe *p, 
310                                    TALLOC_CTX *mem_ctx, 
311                                    struct policy_handle *acct_handle,
312                                    struct dom_sid *sid)
313 {
314         NTSTATUS status;
315         struct lsa_EnumAccountRights r;
316         struct lsa_RightSet rights;
317
318         printf("Testing EnumAccountRights\n");
319
320         r.in.handle = acct_handle;
321         r.in.sid = sid;
322         r.out.rights = &rights;
323
324         status = dcerpc_lsa_EnumAccountRights(p, mem_ctx, &r);
325         if (!NT_STATUS_IS_OK(status)) {
326                 printf("EnumAccountRights failed - %s\n", nt_errstr(status));
327                 return False;
328         }
329
330         NDR_PRINT_DEBUG(lsa_RightSet, r.out.rights);
331
332         return True;
333 }
334
335
336 static BOOL test_QuerySecObj(struct dcerpc_pipe *p, 
337                              TALLOC_CTX *mem_ctx, 
338                              struct policy_handle *acct_handle,
339                              struct dom_sid *sid)
340 {
341         NTSTATUS status;
342         struct lsa_QuerySecObj r;
343
344         printf("Testing QuerySecObj\n");
345
346         r.in.handle = acct_handle;
347         r.in.sec_info = 7;
348
349         status = dcerpc_lsa_QuerySecObj(p, mem_ctx, &r);
350         if (!NT_STATUS_IS_OK(status)) {
351                 printf("QuerySecObj failed - %s\n", nt_errstr(status));
352                 return False;
353         }
354
355         NDR_PRINT_DEBUG(sec_desc_buf, r.out.sd);
356
357         return True;
358 }
359
360 static BOOL test_OpenAccount(struct dcerpc_pipe *p, 
361                              TALLOC_CTX *mem_ctx, 
362                              struct policy_handle *handle,
363                              struct dom_sid *sid)
364 {
365         NTSTATUS status;
366         struct lsa_OpenAccount r;
367         struct policy_handle acct_handle;
368
369         printf("Testing OpenAccount(%s)\n", lsa_sid_string_talloc(mem_ctx, sid));
370
371         r.in.handle = handle;
372         r.in.sid = sid;
373         r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
374         r.out.acct_handle = &acct_handle;
375
376         status = dcerpc_lsa_OpenAccount(p, mem_ctx, &r);
377         if (!NT_STATUS_IS_OK(status)) {
378                 printf("OpenAccount failed - %s\n", nt_errstr(status));
379                 return False;
380         }
381
382         if (!test_EnumPrivsAccount(p, mem_ctx, handle, &acct_handle)) {
383                 return False;
384         }
385
386         if (!test_QuerySecObj(p, mem_ctx, handle, &acct_handle)) {
387                 return False;
388         }
389
390         return True;
391 }
392
393 static BOOL test_EnumAccounts(struct dcerpc_pipe *p, 
394                           TALLOC_CTX *mem_ctx, 
395                           struct policy_handle *handle)
396 {
397         NTSTATUS status;
398         struct lsa_EnumAccounts r;
399         struct lsa_SidArray sids1, sids2;
400         uint32 resume_handle = 0;
401         int i;
402
403         printf("\ntesting EnumAccounts\n");
404
405         r.in.handle = handle;
406         r.in.resume_handle = &resume_handle;
407         r.in.num_entries = 100;
408         r.out.resume_handle = &resume_handle;
409         r.out.sids = &sids1;
410
411         resume_handle = 0;
412         status = dcerpc_lsa_EnumAccounts(p, mem_ctx, &r);
413         if (!NT_STATUS_IS_OK(status)) {
414                 printf("EnumAccounts failed - %s\n", nt_errstr(status));
415                 return False;
416         }
417
418         printf("Got %d sids resume_handle=%u\n", sids1.num_sids, resume_handle);
419
420         NDR_PRINT_DEBUG(lsa_SidArray, r.out.sids);
421
422         if (!test_LookupSids(p, mem_ctx, handle, &sids1)) {
423                 return False;
424         }
425
426         printf("testing all accounts\n");
427         for (i=0;i<sids1.num_sids;i++) {
428                 test_OpenAccount(p, mem_ctx, handle, sids1.sids[i].sid);
429                 test_EnumAccountRights(p, mem_ctx, handle, sids1.sids[i].sid);
430         }
431         printf("\n");
432
433         if (sids1.num_sids < 3) {
434                 return True;
435         }
436         
437         printf("trying EnumAccounts partial listing (asking for 1 at 2)\n");
438         resume_handle = 2;
439         r.in.num_entries = 1;
440         r.out.sids = &sids2;
441
442         status = dcerpc_lsa_EnumAccounts(p, mem_ctx, &r);
443         if (!NT_STATUS_IS_OK(status)) {
444                 printf("EnumAccounts failed - %s\n", nt_errstr(status));
445                 return False;
446         }
447
448         NDR_PRINT_DEBUG(lsa_SidArray, r.out.sids);
449
450         if (sids2.num_sids != 1) {
451                 printf("Returned wrong number of entries (%d)\n", sids2.num_sids);
452                 return False;
453         }
454
455         return True;
456 }
457
458
459 static BOOL test_EnumPrivs(struct dcerpc_pipe *p, 
460                            TALLOC_CTX *mem_ctx, 
461                            struct policy_handle *handle)
462 {
463         NTSTATUS status;
464         struct lsa_EnumPrivs r;
465         struct lsa_PrivArray privs1;
466         uint32 resume_handle = 0;
467
468         printf("\ntesting EnumPrivs\n");
469
470         r.in.handle = handle;
471         r.in.resume_handle = &resume_handle;
472         r.in.max_count = 1000;
473         r.out.resume_handle = &resume_handle;
474         r.out.privs = &privs1;
475
476         resume_handle = 0;
477         status = dcerpc_lsa_EnumPrivs(p, mem_ctx, &r);
478         if (!NT_STATUS_IS_OK(status)) {
479                 printf("EnumPrivs failed - %s\n", nt_errstr(status));
480                 return False;
481         }
482
483         printf("Got %d privs resume_handle=%u\n", privs1.count, resume_handle);
484
485         NDR_PRINT_DEBUG(lsa_PrivArray, r.out.privs);
486
487         return True;
488 }
489
490
491 static BOOL test_EnumTrustDom(struct dcerpc_pipe *p, 
492                               TALLOC_CTX *mem_ctx, 
493                               struct policy_handle *handle)
494 {
495         struct lsa_EnumTrustDom r;
496         NTSTATUS status;
497         uint32 resume_handle = 0;
498         struct lsa_DomainList domains;
499
500         printf("\nTesting EnumTrustDom\n");
501
502         r.in.handle = handle;
503         r.in.resume_handle = &resume_handle;
504         r.in.num_entries = 1000;
505         r.out.domains = &domains;
506         r.out.resume_handle = &resume_handle;
507
508         status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
509         if (!NT_STATUS_IS_OK(status)) {
510                 printf("EnumTrustDom failed - %s\n", nt_errstr(status));
511                 return False;
512         }
513
514         printf("lookup gave %d domains\n", domains.count);
515
516         NDR_PRINT_DEBUG(lsa_DomainList, r.out.domains);
517
518         return True;
519 }
520
521 static BOOL test_QueryInfoPolicy(struct dcerpc_pipe *p, 
522                                  TALLOC_CTX *mem_ctx, 
523                                  struct policy_handle *handle)
524 {
525         struct lsa_QueryInfoPolicy r;
526         NTSTATUS status;
527         int i;
528         BOOL ret = True;
529
530         printf("\nTesting QueryInfoPolicy\n");
531
532         for (i=1;i<13;i++) {
533                 r.in.handle = handle;
534                 r.in.level = i;
535
536                 printf("\ntrying QueryInfoPolicy level %d\n", i);
537
538                 status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
539                 if (!NT_STATUS_IS_OK(status)) {
540                         printf("QueryInfoPolicy failed - %s\n", nt_errstr(status));
541                         ret = False;
542                         continue;
543                 }
544
545                 NDR_PRINT_UNION_DEBUG(lsa_PolicyInformation, r.in.level, r.out.info);
546         }
547
548         return ret;
549 }
550
551 static BOOL test_Delete(struct dcerpc_pipe *p, 
552                        TALLOC_CTX *mem_ctx, 
553                        struct policy_handle *handle)
554 {
555         NTSTATUS status;
556         struct lsa_Delete r;
557
558         printf("\ntesting Delete - but what does it do?\n");
559
560         r.in.handle = handle;
561         status = dcerpc_lsa_Delete(p, mem_ctx, &r);
562         if (!NT_STATUS_IS_OK(status)) {
563                 printf("Delete failed - %s\n", nt_errstr(status));
564                 return False;
565         }
566
567         printf("\n");
568
569         return True;
570 }
571
572 static BOOL test_Close(struct dcerpc_pipe *p, 
573                        TALLOC_CTX *mem_ctx, 
574                        struct policy_handle *handle)
575 {
576         NTSTATUS status;
577         struct lsa_Close r;
578         struct policy_handle handle2;
579
580         printf("\ntesting Close\n");
581
582         r.in.handle = handle;
583         r.out.handle = &handle2;
584
585         status = dcerpc_lsa_Close(p, mem_ctx, &r);
586         if (!NT_STATUS_IS_OK(status)) {
587                 printf("Close failed - %s\n", nt_errstr(status));
588                 return False;
589         }
590
591         status = dcerpc_lsa_Close(p, mem_ctx, &r);
592         /* its really a fault - we need a status code for rpc fault */
593         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
594                 printf("Close failed - %s\n", nt_errstr(status));
595                 return False;
596         }
597
598         printf("\n");
599
600         return True;
601 }
602
603 BOOL torture_rpc_lsa(int dummy)
604 {
605         NTSTATUS status;
606         struct dcerpc_pipe *p;
607         TALLOC_CTX *mem_ctx;
608         BOOL ret = True;
609         struct policy_handle handle;
610
611         mem_ctx = talloc_init("torture_rpc_lsa");
612
613         status = torture_rpc_connection(&p, "lsarpc");
614         if (!NT_STATUS_IS_OK(status)) {
615                 return False;
616         }
617         
618         if (!test_OpenPolicy(p, mem_ctx)) {
619                 ret = False;
620         }
621
622         if (!test_OpenPolicy2(p, mem_ctx, &handle)) {
623                 ret = False;
624         }
625
626         if (!test_EnumAccounts(p, mem_ctx, &handle)) {
627                 ret = False;
628         }
629
630         if (!test_EnumPrivs(p, mem_ctx, &handle)) {
631                 ret = False;
632         }
633
634         if (!test_EnumTrustDom(p, mem_ctx, &handle)) {
635                 ret = False;
636         }
637
638         if (!test_QueryInfoPolicy(p, mem_ctx, &handle)) {
639                 ret = False;
640         }
641         
642 #if 0
643         if (!test_Delete(p, mem_ctx, &handle)) {
644                 ret = False;
645         }
646 #endif
647         
648         if (!test_Close(p, mem_ctx, &handle)) {
649                 ret = False;
650         }
651
652         torture_rpc_close(p);
653
654         return ret;
655 }