baeb95c3ea74528b6369c46c60778eb20bc31553
[metze/samba/wip.git] / source4 / torture / rpc / lsa_lookup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for lsa rpc lookup operations
4
5    Copyright (C) Volker Lendecke 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 #include "includes.h"
22 #include "torture/rpc/rpc.h"
23 #include "librpc/gen_ndr/ndr_lsa_c.h"
24 #include "libcli/security/security.h"
25
26 static bool open_policy(struct torture_context *tctx,
27                         struct dcerpc_binding_handle *b,
28                         struct policy_handle **handle)
29 {
30         struct lsa_ObjectAttribute attr;
31         struct lsa_QosInfo qos;
32         struct lsa_OpenPolicy2 r;
33
34         *handle = talloc(tctx, struct policy_handle);
35         if (!*handle) {
36                 return false;
37         }
38
39         qos.len = 0;
40         qos.impersonation_level = 2;
41         qos.context_mode = 1;
42         qos.effective_only = 0;
43
44         attr.len = 0;
45         attr.root_dir = NULL;
46         attr.object_name = NULL;
47         attr.attributes = 0;
48         attr.sec_desc = NULL;
49         attr.sec_qos = &qos;
50
51         r.in.system_name = "\\";
52         r.in.attr = &attr;
53         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
54         r.out.handle = *handle;
55
56         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenPolicy2_r(b, tctx, &r),
57                 "OpenPolicy2 failed");
58
59         return NT_STATUS_IS_OK(r.out.result);
60 }
61
62 static bool get_domainsid(struct torture_context *tctx,
63                           struct dcerpc_binding_handle *b,
64                           struct policy_handle *handle,
65                           struct dom_sid **sid)
66 {
67         struct lsa_QueryInfoPolicy r;
68         union lsa_PolicyInformation *info = NULL;
69
70         r.in.level = LSA_POLICY_INFO_DOMAIN;
71         r.in.handle = handle;
72         r.out.info = &info;
73
74         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_QueryInfoPolicy_r(b, tctx, &r),
75                 "QueryInfoPolicy failed");
76         torture_assert_ntstatus_ok(tctx, r.out.result, "QueryInfoPolicy failed");
77
78         *sid = info->domain.sid;
79         return true;
80 }
81
82 static NTSTATUS lookup_sids(struct torture_context *tctx,
83                             uint16_t level,
84                             struct dcerpc_binding_handle *b,
85                             struct policy_handle *handle,
86                             struct dom_sid **sids, uint32_t num_sids,
87                             struct lsa_TransNameArray *names)
88 {
89         struct lsa_LookupSids r;
90         struct lsa_SidArray sidarray;
91         struct lsa_RefDomainList *domains;
92         uint32_t count = 0;
93         uint32_t i;
94         NTSTATUS status;
95
96         names->count = 0;
97         names->names = NULL;
98
99         sidarray.num_sids = num_sids;
100         sidarray.sids = talloc_array(tctx, struct lsa_SidPtr, num_sids);
101
102         for (i=0; i<num_sids; i++) {
103                 sidarray.sids[i].sid = sids[i];
104         }
105
106         r.in.handle = handle;
107         r.in.sids = &sidarray;
108         r.in.names = names;
109         r.in.level = level;
110         r.in.count = &count;
111         r.out.names = names;
112         r.out.count = &count;
113         r.out.domains = &domains;
114
115         status = dcerpc_lsa_LookupSids_r(b, tctx, &r);
116         if (!NT_STATUS_IS_OK(status)) {
117                 return status;
118         }
119         return r.out.result;
120 }
121
122 static const char *sid_type_lookup(enum lsa_SidType r)
123 {
124         switch (r) {
125                 case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
126                 case SID_NAME_USER: return "SID_NAME_USER"; break;
127                 case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
128                 case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
129                 case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
130                 case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
131                 case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
132                 case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
133                 case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
134                 case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break;
135         }
136         return "Invalid sid type\n";
137 }
138
139 static bool test_lookupsids(struct torture_context *tctx,
140                             struct dcerpc_binding_handle *b,
141                             struct policy_handle *handle,
142                             struct dom_sid **sids, uint32_t num_sids,
143                             int level, NTSTATUS expected_result, 
144                             enum lsa_SidType *types)
145 {
146         struct lsa_TransNameArray names;
147         NTSTATUS status;
148         uint32_t i;
149         bool ret = true;
150
151         status = lookup_sids(tctx, level, b, handle, sids, num_sids,
152                              &names);
153         if (!NT_STATUS_EQUAL(status, expected_result)) {
154                 printf("For level %d expected %s, got %s\n",
155                        level, nt_errstr(expected_result),
156                        nt_errstr(status));
157                 return false;
158         }
159
160         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK) &&
161             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
162                 return true;
163         }
164
165         for (i=0; i<num_sids; i++) {
166                 if (names.names[i].sid_type != types[i]) {
167                         printf("In level %d, for sid %s expected %s, "
168                                "got %s\n", level,
169                                dom_sid_string(tctx, sids[i]),
170                                sid_type_lookup(types[i]),
171                                sid_type_lookup(names.names[i].sid_type));
172                         ret = false;
173                 }
174         }
175         return ret;
176 }
177
178 static bool get_downleveltrust(struct torture_context *tctx, struct dcerpc_binding_handle *b,
179                                struct policy_handle *handle,
180                                struct dom_sid **sid)
181 {
182         struct lsa_EnumTrustDom r;
183         uint32_t resume_handle = 0;
184         struct lsa_DomainList domains;
185         int i;
186
187         r.in.handle = handle;
188         r.in.resume_handle = &resume_handle;
189         r.in.max_size = 1000;
190         r.out.domains = &domains;
191         r.out.resume_handle = &resume_handle;
192
193         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumTrustDom_r(b, tctx, &r),
194                 "EnumTrustDom failed");
195
196         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NO_MORE_ENTRIES))
197                 torture_fail(tctx, "no trusts");
198
199         if (domains.count == 0) {
200                 torture_fail(tctx, "no trusts");
201         }
202
203         for (i=0; i<domains.count; i++) {
204                 struct lsa_QueryTrustedDomainInfoBySid q;
205                 union lsa_TrustedDomainInfo *info = NULL;
206
207                 if (domains.domains[i].sid == NULL)
208                         continue;
209
210                 q.in.handle = handle;
211                 q.in.dom_sid = domains.domains[i].sid;
212                 q.in.level = 6;
213                 q.out.info = &info;
214
215                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_QueryTrustedDomainInfoBySid_r(b, tctx, &q),
216                         "QueryTrustedDomainInfoBySid failed");
217                 if (!NT_STATUS_IS_OK(q.out.result)) continue;
218
219                 if ((info->info_ex.trust_direction & 2) &&
220                     (info->info_ex.trust_type == 1)) {
221                         *sid = domains.domains[i].sid;
222                         return true;
223                 }
224         }
225
226         torture_fail(tctx, "I need a AD DC with an outgoing trust to NT4");
227 }
228
229 #define NUM_SIDS 8
230
231 bool torture_rpc_lsa_lookup(struct torture_context *torture)
232 {
233         NTSTATUS status;
234         struct dcerpc_pipe *p;
235         bool ret = true;
236         struct policy_handle *handle;
237         struct dom_sid *dom_sid = NULL;
238         struct dom_sid *trusted_sid = NULL;
239         struct dom_sid *sids[NUM_SIDS];
240         struct dcerpc_binding_handle *b;
241
242         status = torture_rpc_connection(torture, &p, &ndr_table_lsarpc);
243         if (!NT_STATUS_IS_OK(status)) {
244                 torture_fail(torture, "unable to connect to table");
245         }
246         b = p->binding_handle;
247
248         ret &= open_policy(torture, b, &handle);
249         if (!ret) return false;
250
251         ret &= get_domainsid(torture, b, handle, &dom_sid);
252         if (!ret) return false;
253
254         ret &= get_downleveltrust(torture, b, handle, &trusted_sid);
255         if (!ret) return false;
256
257         torture_comment(torture, "domain sid: %s\n", 
258                                         dom_sid_string(torture, dom_sid));
259
260         sids[0] = dom_sid_parse_talloc(torture, "S-1-1-0");
261         sids[1] = dom_sid_parse_talloc(torture, "S-1-5-4");
262         sids[2] = dom_sid_parse_talloc(torture, "S-1-5-32");
263         sids[3] = dom_sid_parse_talloc(torture, "S-1-5-32-545");
264         sids[4] = dom_sid_dup(torture, dom_sid);
265         sids[5] = dom_sid_add_rid(torture, dom_sid, 512);
266         sids[6] = dom_sid_dup(torture, trusted_sid);
267         sids[7] = dom_sid_add_rid(torture, trusted_sid, 512);
268
269         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 0,
270                                NT_STATUS_INVALID_PARAMETER, NULL);
271
272         {
273                 enum lsa_SidType types[NUM_SIDS] =
274                         { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN,
275                           SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
276                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
277
278                 ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 1,
279                                        NT_STATUS_OK, types);
280         }
281
282         {
283                 enum lsa_SidType types[NUM_SIDS] =
284                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
285                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
286                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
287                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
288                 ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 2,
289                                        STATUS_SOME_UNMAPPED, types);
290         }
291
292         {
293                 enum lsa_SidType types[NUM_SIDS] =
294                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
295                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
296                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
297                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
298                 ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 3,
299                                        STATUS_SOME_UNMAPPED, types);
300         }
301
302         {
303                 enum lsa_SidType types[NUM_SIDS] =
304                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
305                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
306                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
307                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
308                 ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 4,
309                                        STATUS_SOME_UNMAPPED, types);
310         }
311
312         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 5,
313                                NT_STATUS_NONE_MAPPED, NULL);
314
315         {
316                 enum lsa_SidType types[NUM_SIDS] =
317                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
318                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
319                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
320                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
321                 ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 6,
322                                        STATUS_SOME_UNMAPPED, types);
323         }
324
325         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 7,
326                                NT_STATUS_INVALID_PARAMETER, NULL);
327         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 8,
328                                NT_STATUS_INVALID_PARAMETER, NULL);
329         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 9,
330                                NT_STATUS_INVALID_PARAMETER, NULL);
331         ret &= test_lookupsids(torture, b, handle, sids, NUM_SIDS, 10,
332                                NT_STATUS_INVALID_PARAMETER, NULL);
333
334         return ret;
335 }
336
337 static bool test_LookupSidsReply(struct torture_context *tctx,
338                                  struct dcerpc_pipe *p)
339 {
340         struct policy_handle *handle;
341
342         struct dom_sid **sids;
343         uint32_t num_sids = 1;
344
345         struct lsa_LookupSids r;
346         struct lsa_SidArray sidarray;
347         struct lsa_RefDomainList *domains = NULL;
348         struct lsa_TransNameArray names;
349         uint32_t count = 0;
350
351         uint32_t i;
352         const char *dom_sid = "S-1-5-21-1111111111-2222222222-3333333333";
353         const char *dom_admin_sid;
354         struct dcerpc_binding_handle *b = p->binding_handle;
355
356         if (!open_policy(tctx, b, &handle)) {
357                 return false;
358         }
359
360         dom_admin_sid = talloc_asprintf(tctx, "%s-%d", dom_sid, 512);
361
362         sids = talloc_array(tctx, struct dom_sid *, num_sids);
363
364         sids[0] = dom_sid_parse_talloc(tctx, dom_admin_sid);
365
366         names.count = 0;
367         names.names = NULL;
368
369         sidarray.num_sids = num_sids;
370         sidarray.sids = talloc_array(tctx, struct lsa_SidPtr, num_sids);
371
372         for (i=0; i<num_sids; i++) {
373                 sidarray.sids[i].sid = sids[i];
374         }
375
376         r.in.handle     = handle;
377         r.in.sids       = &sidarray;
378         r.in.names      = &names;
379         r.in.level      = LSA_LOOKUP_NAMES_ALL;
380         r.in.count      = &count;
381         r.out.names     = &names;
382         r.out.count     = &count;
383         r.out.domains   = &domains;
384
385         torture_assert_ntstatus_ok(tctx, dcerpc_lsa_LookupSids_r(b, tctx, &r),
386                 "LookupSids failed");
387
388         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NONE_MAPPED,
389                 "unexpected error code");
390
391         torture_assert_int_equal(tctx, names.count, num_sids,
392                 "unexpected names count");
393         torture_assert(tctx, names.names,
394                 "unexpected names pointer");
395         torture_assert_str_equal(tctx, names.names[0].name.string, dom_admin_sid,
396                 "unexpected names[0].string");
397
398 #if 0
399         /* vista sp1 passes, w2k3 sp2 fails */
400         torture_assert_int_equal(tctx, domains->count, num_sids,
401                 "unexpected domains count");
402         torture_assert(tctx, domains->domains,
403                 "unexpected domains pointer");
404         torture_assert_str_equal(tctx, dom_sid_string(tctx, domains->domains[0].sid), dom_sid,
405                 "unexpected domain sid");
406 #endif
407
408         return true;
409 }
410
411 /* check for lookup sids results */
412 struct torture_suite *torture_rpc_lsa_lookup_sids(TALLOC_CTX *mem_ctx)
413 {
414         struct torture_suite *suite;
415         struct torture_rpc_tcase *tcase;
416
417         suite = torture_suite_create(mem_ctx, "LSA-LOOKUPSIDS");
418         tcase = torture_suite_add_rpc_iface_tcase(suite, "lsa",
419                                                   &ndr_table_lsarpc);
420
421         torture_rpc_tcase_add_test(tcase, "LookupSidsReply", test_LookupSidsReply);
422
423         return suite;
424 }