d90c3694a9adffea46cca9b16d05644abb552010
[jelmer/samba4-debian.git] / source / 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         NTSTATUS status;
70
71         r.in.level = LSA_POLICY_INFO_DOMAIN;
72         r.in.handle = handle;
73
74         status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
75         if (!NT_STATUS_IS_OK(status)) return False;
76
77         *sid = r.out.info->domain.sid;
78         return True;
79 }
80
81 static NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, uint16_t level,
82                             struct dcerpc_pipe *p,
83                             struct policy_handle *handle,
84                             struct dom_sid **sids, uint32_t num_sids,
85                             struct lsa_TransNameArray *names)
86 {
87         struct lsa_LookupSids r;
88         struct lsa_SidArray sidarray;
89         uint32_t count = 0;
90         uint32_t i;
91
92         names->count = 0;
93         names->names = NULL;
94
95         sidarray.num_sids = num_sids;
96         sidarray.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids);
97
98         for (i=0; i<num_sids; i++) {
99                 sidarray.sids[i].sid = sids[i];
100         }
101
102         r.in.handle = handle;
103         r.in.sids = &sidarray;
104         r.in.names = names;
105         r.in.level = level;
106         r.in.count = &count;
107         r.out.names = names;
108         r.out.count = &count;
109
110         return dcerpc_lsa_LookupSids(p, mem_ctx, &r);
111 }
112
113 static const char *sid_type_lookup(enum lsa_SidType r)
114 {
115         switch (r) {
116                 case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
117                 case SID_NAME_USER: return "SID_NAME_USER"; break;
118                 case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
119                 case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
120                 case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
121                 case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
122                 case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
123                 case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
124                 case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
125         }
126         return "Invalid sid type\n";
127 }
128
129 static BOOL test_lookupsids(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
130                             struct policy_handle *handle,
131                             struct dom_sid **sids, uint32_t num_sids,
132                             int level, NTSTATUS expected_result, 
133                             enum lsa_SidType *types)
134 {
135         struct lsa_TransNameArray names;
136         NTSTATUS status;
137         uint32_t i;
138         BOOL ret = True;
139
140         status = lookup_sids(mem_ctx, level, p, handle, sids, num_sids,
141                              &names);
142         if (!NT_STATUS_EQUAL(status, expected_result)) {
143                 printf("For level %d expected %s, got %s\n",
144                        level, nt_errstr(expected_result),
145                        nt_errstr(status));
146                 return False;
147         }
148
149         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK) &&
150             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
151                 return True;
152         }
153
154         for (i=0; i<num_sids; i++) {
155                 if (names.names[i].sid_type != types[i]) {
156                         printf("In level %d, for sid %s expected %s, "
157                                "got %s\n", level,
158                                dom_sid_string(mem_ctx, sids[i]),
159                                sid_type_lookup(types[i]),
160                                sid_type_lookup(names.names[i].sid_type));
161                         ret = False;
162                 }
163         }
164         return ret;
165 }
166
167 static BOOL get_downleveltrust(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
168                                struct policy_handle *handle,
169                                struct dom_sid **sid)
170 {
171         struct lsa_EnumTrustDom r;
172         uint32_t resume_handle = 0;
173         struct lsa_DomainList domains;
174         NTSTATUS status;
175         int i;
176
177         r.in.handle = handle;
178         r.in.resume_handle = &resume_handle;
179         r.in.max_size = 1000;
180         r.out.domains = &domains;
181         r.out.resume_handle = &resume_handle;
182
183         status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
184
185         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
186                 printf("no trusts\n");
187                 return False;
188         }
189
190         if (domains.count == 0) {
191                 printf("no trusts\n");
192                 return False;
193         }
194
195         for (i=0; i<domains.count; i++) {
196                 struct lsa_QueryTrustedDomainInfoBySid q;
197
198                 if (domains.domains[i].sid == NULL)
199                         continue;
200
201                 q.in.handle = handle;
202                 q.in.dom_sid = domains.domains[i].sid;
203                 q.in.level = 6;
204                 status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q);
205                 if (!NT_STATUS_IS_OK(status)) continue;
206
207                 if ((q.out.info->info_ex.trust_direction & 2) &&
208                     (q.out.info->info_ex.trust_type == 1)) {
209                         *sid = domains.domains[i].sid;
210                         return True;
211                 }
212         }
213
214         printf("I need a AD DC with an outgoing trust to NT4\n");
215         return False;
216 }
217
218 #define NUM_SIDS 8
219
220 BOOL torture_rpc_lsa_lookup(struct torture_context *torture)
221 {
222         NTSTATUS status;
223         struct dcerpc_pipe *p;
224         TALLOC_CTX *mem_ctx;
225         BOOL ret = True;
226         struct policy_handle *handle;
227         struct dom_sid *dom_sid;
228         struct dom_sid *trusted_sid;
229         struct dom_sid *sids[NUM_SIDS];
230
231         mem_ctx = talloc_init("torture_rpc_lsa");
232
233         status = torture_rpc_connection(torture, &p, &ndr_table_lsarpc);
234         if (!NT_STATUS_IS_OK(status)) {
235                 ret = False;
236                 goto done;
237         }
238
239         ret &= open_policy(mem_ctx, p, &handle);
240         if (!ret) goto done;
241
242         ret &= get_domainsid(mem_ctx, p, handle, &dom_sid);
243         if (!ret) goto done;
244
245         ret &= get_downleveltrust(mem_ctx, p, handle, &trusted_sid);
246         if (!ret) goto done;
247
248         printf("domain sid: %s\n", dom_sid_string(mem_ctx, dom_sid));
249
250         sids[0] = dom_sid_parse_talloc(mem_ctx, "S-1-1-0");
251         sids[1] = dom_sid_parse_talloc(mem_ctx, "S-1-5-4");
252         sids[2] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
253         sids[3] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545");
254         sids[4] = dom_sid_dup(mem_ctx, dom_sid);
255         sids[5] = dom_sid_add_rid(mem_ctx, dom_sid, 512);
256         sids[6] = dom_sid_dup(mem_ctx, trusted_sid);
257         sids[7] = dom_sid_add_rid(mem_ctx, trusted_sid, 512);
258
259         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 0,
260                                NT_STATUS_INVALID_PARAMETER, NULL);
261
262         {
263                 enum lsa_SidType types[NUM_SIDS] =
264                         { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN,
265                           SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
266                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
267
268                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 1,
269                                        NT_STATUS_OK, types);
270         }
271
272         {
273                 enum lsa_SidType types[NUM_SIDS] =
274                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
275                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
276                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
277                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
278                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 2,
279                                        STATUS_SOME_UNMAPPED, 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_UNKNOWN, SID_NAME_UNKNOWN };
288                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 3,
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(mem_ctx, p, handle, sids, NUM_SIDS, 4,
299                                        STATUS_SOME_UNMAPPED, types);
300         }
301
302         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 5,
303                                NT_STATUS_NONE_MAPPED, NULL);
304
305         {
306                 enum lsa_SidType types[NUM_SIDS] =
307                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
308                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
309                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
310                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
311                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 6,
312                                        STATUS_SOME_UNMAPPED, types);
313         }
314
315         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 7,
316                                NT_STATUS_INVALID_PARAMETER, NULL);
317         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 8,
318                                NT_STATUS_INVALID_PARAMETER, NULL);
319         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 9,
320                                NT_STATUS_INVALID_PARAMETER, NULL);
321         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 10,
322                                NT_STATUS_INVALID_PARAMETER, NULL);
323
324  done:
325         talloc_free(mem_ctx);
326
327         return ret;
328 }