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