2 Unix SMB/CIFS implementation.
3 test suite for lsa rpc lookup operations
5 Copyright (C) Volker Lendecke 2006
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.
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.
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/>.
22 #include "torture/rpc/torture_rpc.h"
23 #include "librpc/gen_ndr/ndr_lsa_c.h"
24 #include "libcli/security/security.h"
26 static bool open_policy(struct torture_context
*tctx
,
27 struct dcerpc_binding_handle
*b
,
28 struct policy_handle
**handle
)
30 struct lsa_ObjectAttribute attr
;
31 struct lsa_QosInfo qos
;
32 struct lsa_OpenPolicy2 r
;
34 *handle
= talloc(tctx
, struct policy_handle
);
40 qos
.impersonation_level
= 2;
42 qos
.effective_only
= 0;
46 attr
.object_name
= NULL
;
51 r
.in
.system_name
= "\\";
53 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
54 r
.out
.handle
= *handle
;
56 torture_assert_ntstatus_ok(tctx
, dcerpc_lsa_OpenPolicy2_r(b
, tctx
, &r
),
57 "OpenPolicy2 failed");
59 return NT_STATUS_IS_OK(r
.out
.result
);
62 static bool get_domainsid(struct torture_context
*tctx
,
63 struct dcerpc_binding_handle
*b
,
64 struct policy_handle
*handle
,
67 struct lsa_QueryInfoPolicy r
;
68 union lsa_PolicyInformation
*info
= NULL
;
70 r
.in
.level
= LSA_POLICY_INFO_DOMAIN
;
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");
78 *sid
= info
->domain
.sid
;
82 static NTSTATUS
lookup_sids(struct torture_context
*tctx
,
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
)
89 struct lsa_LookupSids r
;
90 struct lsa_SidArray sidarray
;
91 struct lsa_RefDomainList
*domains
;
99 sidarray
.num_sids
= num_sids
;
100 sidarray
.sids
= talloc_array(tctx
, struct lsa_SidPtr
, num_sids
);
102 for (i
=0; i
<num_sids
; i
++) {
103 sidarray
.sids
[i
].sid
= sids
[i
];
106 r
.in
.handle
= handle
;
107 r
.in
.sids
= &sidarray
;
112 r
.out
.count
= &count
;
113 r
.out
.domains
= &domains
;
115 status
= dcerpc_lsa_LookupSids_r(b
, tctx
, &r
);
116 if (!NT_STATUS_IS_OK(status
)) {
122 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
)
129 struct lsa_TransNameArray names
;
134 status
= lookup_sids(tctx
, level
, b
, handle
, sids
, num_sids
,
136 if (!NT_STATUS_EQUAL(status
, expected_result
)) {
137 printf("For level %d expected %s, got %s\n",
138 level
, nt_errstr(expected_result
),
143 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OK
) &&
144 !NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
148 for (i
=0; i
<num_sids
; i
++) {
149 if (names
.names
[i
].sid_type
!= types
[i
]) {
150 printf("In level %d, for sid %s expected %s, "
152 dom_sid_string(tctx
, sids
[i
]),
153 sid_type_lookup(types
[i
]),
154 sid_type_lookup(names
.names
[i
].sid_type
));
161 static bool get_downleveltrust(struct torture_context
*tctx
, struct dcerpc_binding_handle
*b
,
162 struct policy_handle
*handle
,
163 struct dom_sid
**sid
)
165 struct lsa_EnumTrustDom r
;
166 uint32_t resume_handle
= 0;
167 struct lsa_DomainList domains
;
170 r
.in
.handle
= handle
;
171 r
.in
.resume_handle
= &resume_handle
;
172 r
.in
.max_size
= 1000;
173 r
.out
.domains
= &domains
;
174 r
.out
.resume_handle
= &resume_handle
;
176 torture_assert_ntstatus_ok(tctx
, dcerpc_lsa_EnumTrustDom_r(b
, tctx
, &r
),
177 "EnumTrustDom failed");
179 if (NT_STATUS_EQUAL(r
.out
.result
, NT_STATUS_NO_MORE_ENTRIES
))
180 torture_fail(tctx
, "no trusts");
182 if (domains
.count
== 0) {
183 torture_fail(tctx
, "no trusts");
186 for (i
=0; i
<domains
.count
; i
++) {
187 struct lsa_QueryTrustedDomainInfoBySid q
;
188 union lsa_TrustedDomainInfo
*info
= NULL
;
190 if (domains
.domains
[i
].sid
== NULL
)
193 q
.in
.handle
= handle
;
194 q
.in
.dom_sid
= domains
.domains
[i
].sid
;
198 torture_assert_ntstatus_ok(tctx
, dcerpc_lsa_QueryTrustedDomainInfoBySid_r(b
, tctx
, &q
),
199 "QueryTrustedDomainInfoBySid failed");
200 if (!NT_STATUS_IS_OK(q
.out
.result
)) continue;
202 if ((info
->info_ex
.trust_direction
& 2) &&
203 (info
->info_ex
.trust_type
== 1)) {
204 *sid
= domains
.domains
[i
].sid
;
209 torture_fail(tctx
, "I need a AD DC with an outgoing trust to NT4");
214 bool torture_rpc_lsa_lookup(struct torture_context
*torture
)
217 struct dcerpc_pipe
*p
;
219 struct policy_handle
*handle
;
220 struct dom_sid
*dom_sid
= NULL
;
221 struct dom_sid
*trusted_sid
= NULL
;
222 struct dom_sid
*sids
[NUM_SIDS
];
223 struct dcerpc_binding_handle
*b
;
224 enum dcerpc_transport_t transport
;
226 status
= torture_rpc_connection(torture
, &p
, &ndr_table_lsarpc
);
227 if (!NT_STATUS_IS_OK(status
)) {
228 torture_fail(torture
, "unable to connect to table");
230 b
= p
->binding_handle
;
231 transport
= dcerpc_binding_handle_get_transport(b
);
233 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
234 torture_comment(torture
,
235 "torture_rpc_lsa_lookup is only available "
236 "over NCACN_NP or NCALRPC");
240 ret
&= open_policy(torture
, b
, &handle
);
241 if (!ret
) return false;
243 ret
&= get_domainsid(torture
, b
, handle
, &dom_sid
);
244 if (!ret
) return false;
246 ret
&= get_downleveltrust(torture
, b
, handle
, &trusted_sid
);
247 if (!ret
) return false;
249 torture_comment(torture
, "domain sid: %s\n",
250 dom_sid_string(torture
, dom_sid
));
252 sids
[0] = dom_sid_parse_talloc(torture
, "S-1-1-0");
253 sids
[1] = dom_sid_parse_talloc(torture
, "S-1-5-4");
254 sids
[2] = dom_sid_parse_talloc(torture
, "S-1-5-32");
255 sids
[3] = dom_sid_parse_talloc(torture
, "S-1-5-32-545");
256 sids
[4] = dom_sid_dup(torture
, dom_sid
);
257 sids
[5] = dom_sid_add_rid(torture
, dom_sid
, 512);
258 sids
[6] = dom_sid_dup(torture
, trusted_sid
);
259 sids
[7] = dom_sid_add_rid(torture
, trusted_sid
, 512);
261 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 0,
262 NT_STATUS_INVALID_PARAMETER
, NULL
);
265 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
};
270 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 1,
271 NT_STATUS_OK
, types
);
275 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 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 2,
281 STATUS_SOME_UNMAPPED
, types
);
285 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 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 3,
291 STATUS_SOME_UNMAPPED
, types
);
295 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 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 4,
301 STATUS_SOME_UNMAPPED
, types
);
304 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 5,
305 NT_STATUS_NONE_MAPPED
, NULL
);
308 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 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 6,
314 STATUS_SOME_UNMAPPED
, types
);
317 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 7,
318 NT_STATUS_INVALID_PARAMETER
, NULL
);
319 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 8,
320 NT_STATUS_INVALID_PARAMETER
, NULL
);
321 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 9,
322 NT_STATUS_INVALID_PARAMETER
, NULL
);
323 ret
&= test_lookupsids(torture
, b
, handle
, sids
, NUM_SIDS
, 10,
324 NT_STATUS_INVALID_PARAMETER
, NULL
);
329 static bool test_LookupSidsReply(struct torture_context
*tctx
,
330 struct dcerpc_pipe
*p
)
332 struct policy_handle
*handle
= NULL
;
334 struct dom_sid
**sids
= NULL
;
335 uint32_t num_sids
= 1;
337 struct lsa_LookupSids r
;
338 struct lsa_SidArray sidarray
;
339 struct lsa_RefDomainList
*domains
= NULL
;
340 struct lsa_TransNameArray names
;
344 const char *dom_sid
= "S-1-5-21-1111111111-2222222222-3333333333";
345 const char *dom_admin_sid
;
346 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
347 enum dcerpc_transport_t transport
=
348 dcerpc_binding_handle_get_transport(b
);
351 ZERO_STRUCT(sidarray
);
354 if (transport
!= NCACN_NP
&& transport
!= NCALRPC
) {
355 torture_comment(tctx
,
356 "test_LookupSidsReply is only available "
357 "over NCACN_NP or NCALRPC");
361 if (!open_policy(tctx
, b
, &handle
)) {
365 dom_admin_sid
= talloc_asprintf(tctx
, "%s-%d", dom_sid
, 512);
367 sids
= talloc_zero_array(tctx
, struct dom_sid
*, num_sids
);
369 sids
[0] = dom_sid_parse_talloc(tctx
, dom_admin_sid
);
374 sidarray
.num_sids
= num_sids
;
375 sidarray
.sids
= talloc_zero_array(tctx
, struct lsa_SidPtr
, num_sids
);
377 for (i
=0; i
<num_sids
; i
++) {
378 sidarray
.sids
[i
].sid
= sids
[i
];
381 r
.in
.handle
= handle
;
382 r
.in
.sids
= &sidarray
;
384 r
.in
.level
= LSA_LOOKUP_NAMES_ALL
;
386 r
.out
.names
= &names
;
387 r
.out
.count
= &count
;
388 r
.out
.domains
= &domains
;
390 torture_assert_ntstatus_ok(tctx
, dcerpc_lsa_LookupSids_r(b
, tctx
, &r
),
391 "LookupSids failed");
393 torture_assert_ntstatus_equal(tctx
, r
.out
.result
, NT_STATUS_NONE_MAPPED
,
394 "unexpected error code");
396 torture_assert_int_equal(tctx
, names
.count
, num_sids
,
397 "unexpected names count");
398 torture_assert(tctx
, names
.names
,
399 "unexpected names pointer");
400 torture_assert_str_equal(tctx
, names
.names
[0].name
.string
, dom_admin_sid
,
401 "unexpected names[0].string");
404 /* vista sp1 passes, w2k3 sp2 fails */
405 torture_assert_int_equal(tctx
, domains
->count
, num_sids
,
406 "unexpected domains count");
407 torture_assert(tctx
, domains
->domains
,
408 "unexpected domains pointer");
409 torture_assert_str_equal(tctx
, dom_sid_string(tctx
, domains
->domains
[0].sid
), dom_sid
,
410 "unexpected domain sid");
416 /* check for lookup sids results */
417 struct torture_suite
*torture_rpc_lsa_lookup_sids(TALLOC_CTX
*mem_ctx
)
419 struct torture_suite
*suite
;
420 struct torture_rpc_tcase
*tcase
;
422 suite
= torture_suite_create(mem_ctx
, "lsa.lookupsids");
423 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "lsa",
426 torture_rpc_tcase_add_test(tcase
, "LookupSidsReply", test_LookupSidsReply
);