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